Binding of Button inside a ListView item (Xamarin) - c#

I have been trying all the "Qs that may have your answer" 3 days later, still no joy.
I have a XAML Page that holds a ListView of products and their details, using binding to a model called RackProducts as you can see:
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="PapillonWine.PapillonRackCatalogPage"
xmlns:local="clr-namespace:PapillonWine;assembly=PapillonWine"
xmlns:artina="clr-namespace:UXDivers.Artina.Shared;assembly=UXDivers.Artina.Shared"
xmlns:customContentView="clr-namespace:PapillonWine.NavBars"
Title="{ artina:Translate PageTitleProductsCatalog }"
BackgroundColor="{ DynamicResource MainWrapperBackgroundColor }"
x:Name="CatalogItemPage">
<ContentPage.Content>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="70" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<customContentView:CustomNavigationBar Grid.Row="0" x:Name="NavigationBarView" BackgroundColor="Transparent"/>
<ListView
x:Name="PapillonRackItems"
Grid.Row="1"
ItemsSource="{ Binding RackProducts }"
HasUnevenRows="True"
ItemSelected="OnItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<local:PapillonCatalogItemTemplate />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</ContentPage.Content>
</ContentPage>
Each product is displayed using the PapillonCatalogItemTemplate which holds four buttons (to view a carousel of product images, to add to cart, to view dimensions and lastly to share the product). This PapillonCatalogItemTemplate is as follows:
<?xml version="1.0" encoding="utf-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="PapillonWine.PapillonCatalogItemTemplate"
xmlns:local="clr-namespace:PapillonWine;assembly=PapillonWine"
xmlns:artina="clr-namespace:UXDivers.Artina.Shared;assembly=UXDivers.Artina.Shared"
xmlns:customContentView="clr-namespace:PapillonWine.NavBars"
xmlns:ffimageloading="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
xmlns:fftransformations="clr-namespace:FFImageLoading.Transformations;assembly=FFImageLoading.Transformations"
Padding="10" BackgroundColor="{ DynamicResource MainWrapperBackgroundColor }"
x:Name="CatalogItemTemplate">
<!-- FAVORITE ICON -->
<Grid>
<!-- COLUMN DEFS -->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- ROW DEFS -->
<Grid.RowDefinitions>
<RowDefinition Height="0.45*" />
<RowDefinition><RowDefinition.Height><OnIdiom x:TypeArguments="GridLength" Phone="200" Tablet="400" /></RowDefinition.Height></RowDefinition>
</Grid.RowDefinitions>
<StackLayout Grid.Column="0" Grid.Row="0" Spacing="5" HorizontalOptions="FillAndExpand" WidthRequest="1000" >
<!-- PRODUCT NAME -->
<Label Text="{ Binding Name }" />
<!-- DESCRIPTION -->
<Label Text="{Binding Description}" />
<!-- BUTTONS -->
<StackLayout x:Name="buttonstack" Orientation="Horizontal" >
<!-- SHOW IMAGES -->
<artina:Button
x:Name="ImageCarousel"
Text="{ x:Static local:FontAwesomeWeb511Font.CameraRetro }"
Style="{StaticResource FontIcon}"
BindingContext="{Binding Source={x:Reference CatalogItemTemplate}, Path=BindingContext}"
Command="{Binding OnClickViewImageCarousel}"
CommandParameter="{Binding Source={x:Reference buttonstack}, Path=BindingContext}" >
<!-- SHOW CART -->
<artina:Button
Text="{ x:Static local:FontAwesomeWeb511Font.cartplus }"
Style="{StaticResource FontIcon}"
Clicked="OnBuyItemSelected">
</artina:Button>
<!-- SHOW DIMENSIONS -->
<artina:Button
Text="{ x:Static local:FontAwesomeWeb511Font.RulerCombined }"
Style="{StaticResource FontIcon}"
Clicked="OnDimensionsSelected" >
<!-- SHOW IMAGES -->
<artina:Button
Text="{ x:Static local:FontAwesomeFont.Share }"
Style="{StaticResource FontIcon}"
Clicked="OnShareSelected" >
</StackLayout>
</StackLayout>
<ffimageloading:CachedImage
Grid.Column="0" Grid.Row="1"
Source="{ Binding Image }" />
</Grid>
</ContentView>
If I click the ffloading image at the bottom of the template item, the OnItemSelected button fires, and I get a nice new view page with a picture of the product that I selected and all its item details... bully! The code it fires is as follows:
public async void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var selectedItem = ((ListView)sender).SelectedItem;
var page = new PapillonRackItemViewPage(((RackProduct)selectedItem).Id);
await Navigation.PushModalAsync(page);
}
However... if I try to fire one of the buttons within the item template (for example the one directly beneath "SHOW IMAGES", nothing happens. I have left the Commmand, CommandParameter and Binding arguments in that first button but I'm not sure they're correct. I have tried ICommand route, TapGestureRecognizer route, and tried most similar posts, and I really need help on this one. How do I pass the same binding context as in the ListView and its "RackProducts" binding, through button items within a list view? Any chance of a much needed helping hand? Thanks!

in your XAML
Clicked="OnClickViewImageCarousel" CommandParameter="{Binding .}"
then in the code behind
protected void OnClickViewImageCarousel(object sender, EventArgs e)
{
var selectedItem = (RackProduct)((Button)sender).CommandParameter;
}

Related

Picker ItemSource values not binding in a XAML ListView

Hoping you can advise as I've tried all methods to bind a picker in a Listview to my item source values using both code-behind and MVVM. The picker binding works outside of the ListView, but not inside - is this out of the box or just not possible?
Please see my list below!
code
<ListView
x:Name="TypesList"
HeightRequest="53"
BackgroundColor="White"
IsGroupingEnabled="True"
IsPullToRefreshEnabled="false"
ItemsSource="{Binding Items}"
IsRefreshing="{Binding IsBusy}"
RefreshCommand="{Binding LoadTypesCommand}"
SeparatorVisibility="None"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell Height="63">
<StackLayout Orientation="Horizontal" VerticalOptions="Center">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="150"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="70"/>
</Grid.ColumnDefinitions>
<!-- -->
<Label Grid.Column="0"
Grid.Row="0"
VerticalOptions="Center"
FontAttributes="None"
Text="{Binding .Name, Mode=TwoWay} "
TextColor="Black"
VerticalTextAlignment="Center"
Margin="0,15,0,110"
BackgroundColor="White"
Padding="20,10,0,10"
FontFamily="Hiragino Sans"
FontSize="14"
HeightRequest="53"
x:Name="userLabel"
/>
<Entry Grid.Column="1"
Grid.Row="0"
Text="{Binding .Amount, Mode=TwoWay}"
TextColor="Black"
VerticalOptions="EndAndExpand"
Margin="0,15,20,110"
BackgroundColor="White"
FontFamily="Hiragino Sans"
FontSize="14"
HeightRequest="40"
WidthRequest="55"
x:Name="userEntry"
/>
<Picker Grid.Column="2"
Grid.Row="0"
x:Name="mPicker"
ItemsSource="{Binding UserOptions}"
/>
</Grid>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
code
Code behind
code
mPicker.ItemsSource = ViewModel.UserOptions;
code
The model allocates UserOptions and this works for a picker outside the listview so I don't believe there is anything wrong with the model or this code needs to be posted.
Any help appreciated!
List view has its own binding context. So you need to get binding context of view model and then bind to picker like this
Set a name of your view like this
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="viewName">
<Picker Grid.Column="2"
Grid.Row="0"
x:Name="mPicker"
ItemsSource="{Binding BindingContext.UserOptions, Source={x:Reference viewName}}"
/>

Xamarin.Forms: Add click event to map in <Grid>?

I was finally able to display the ListView using a <Grid> when clicking on a button. This is the xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"
xmlns:local="clr-namespace:GasStations"
x:Class="GasStations.MainPage">
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="50" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<StackLayout Grid.Row="0" x:Name="MapGrid">
<maps:Map WidthRequest="960" HeightRequest="200"
x:Name="MyMap" IsShowingUser="true"/>
</StackLayout>
<StackLayout Grid.Row="1">
<Button Text="Show List" x:Name="Button_DisplayList"
VerticalOptions="CenterAndExpand"
HorizontalOptions="Center"
Clicked="OnButtonClicked" />
</StackLayout>
<StackLayout Grid.Row="2" x:Name="listSection" IsVisible="false" HeightRequest="200">
<ListView x:Name="ListView_Pets">
<ListView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>dog</x:String>
<x:String>cat</x:String>
<x:String>bird</x:String>
</x:Array>
</ListView.ItemsSource>
</ListView>
</StackLayout>
</Grid>
</ContentPage>
And this is the codebehind:
void OnButtonClicked(object sender, EventArgs args)
{
listSection.IsVisible = true;
Button_DisplayList.IsVisible = false;
}
When I click the button, the ListView is displayed and the button is hidden. So far so good.
Once the ListView is open, how can I hide the ListView again when I tap on the map?
I tried using GestureRecognizers and <TapGestureRecognizer Tapped="OnTapGestureRecognizerTapped"/>, but it doesn't build.
Any help is appreciated.
I've included screenshots because I'm still learning the terminology.
Adding gesture recognizer on the parent stacklayout of the map
On xaml:
<StackLayout Grid.Row="0" x:Name="MapGrid">
<StackLayout.GestureRecognizer>
<TapGestureRecognizer Tapped="OnMapAreaTapped"/>
</StackLayout.GestureRecognizer>
<maps:Map WidthRequest="960" HeightRequest="200" x:Name="MyMap" IsShowingUser="true"/>
</StackLayout>
On code behind:
private void OnMapAreaTapped(object sen, EventArgs e)
{
listSection.IsVisible = false;
Button_DisplayList.IsVisible = true;
}

Set navigation side menu background image in Xamarin Forms

In Xamarin forms I want to use an image ( png file ) I created as background for a side "hamburger" menu. For example, here is some menu:
Two questions:
1) What's the best image size to use for the menu background
2) How do I put a ListView that contains my menu options on top of the background image ?
I tried using the grid but wasn't successful at stacking them. Code below is a quick summary of how the MasterDetailPage is structured.
//Menu
<MasterDetailPage.Master>
<ContentPage>
<ContentPpage.Content>
<AbsoluteLayout> //Also tried FlexLayout and RelativeLayout
<Image Source="blah" Aspect="Fill"/>
<Grid>
<ListView/>
</Grid>
</AbsoluteLayout>
</ContentPpage.Content>
<ContentPage>
</MasterDetailPage.Master>
//Page content
<MasterDetailPage.Detail>
<ContentPage>
///Page content
</ContentPage>
</MasterDetailPage.Detail>
The goal is to get the side menu looking something like this:
I just tried one sample solution. This is my master page :
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="using:MasterDetailPageNavigation"
x:Class="MasterDetailPageNavigation.MasterPage"
Padding="0,40,0,0"
Icon="hamburger.png"
Title="Personal Organiser">
<Grid>
<Image Source="Default-Portrait.png" Aspect="AspectFill" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"/>
<StackLayout Margin="0,20,0,0">
<ListView x:Name="listView" x:FieldModifier="public" BackgroundColor="Transparent">
<ListView.ItemsSource>
<x:Array Type="{x:Type local:MasterPageItem}">
<local:MasterPageItem Title="Contacts" IconSource="contacts.png" TargetType="{x:Type local:ContactsPage}" />
<local:MasterPageItem Title="TodoList" IconSource="todo.png" TargetType="{x:Type local:TodoListPage}" />
<local:MasterPageItem Title="Reminders" IconSource="reminders.png" TargetType="{x:Type local:ReminderPage}" />
</x:Array>
</ListView.ItemsSource>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="5,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="{Binding IconSource}" />
<Label Grid.Column="1" Text="{Binding Title}" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</Grid>
</ContentPage>
There is a trick to have Grid as a parent. If you put 2 controls in same Cell it will overlap. Here my background image "Default-Portrait" will get overlapped by my StackLayout (listview) which has Background Color set as "Transparent".
For the Size of the Image, I would use multiple Size and put those images in the appropriate drawable-hdpi directory in android and iOS assets.
Let me know if you need any more clarifications.
This is a result:

CarouselView not showing the data

I am trying to display a CarouselView inside a TabbedPage. I already added the (prerelease-)packages to the Project. Here is my xaml file:
<control:CarouselView x:Name="CVMain"
HeightRequest="150" >
<control:CarouselView.ItemTemplate>
<DataTemplate>
<Label HorizontalOptions="Center"
Text="Just a test :)"
VerticalOptions="Center" />
</DataTemplate>
</control:CarouselView.ItemTemplate>
</control:CarouselView>
(control: xmlns:control="clr-namespace:Xamarin.Forms;assembly=Xamarin.Forms.CarouselView")
The label doesn't show up when I launch my app. The carousel still exists tho, I can confirm that by adding the BackgroundColor="Green"attribute to the CarouselView.
What am I missing?
Edit: As suggested, I placed the Label inside a Grid, but without any success (I also added an Image):
<control:CarouselView x:Name="CVMain" HeightRequest="150">
<control:CarouselView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image Grid.RowSpan="2"
Aspect="AspectFill"
Source="{Binding ImageBase64,
Converter={StaticResource Base64ToImageConverter}}" />
<StackLayout Grid.Row="1">
<Label Text="Test123" />
</StackLayout>
</Grid>
</DataTemplate>
</control:CarouselView.ItemTemplate>
</control:CarouselView>

How to add buttons underneath a Xamarin.Forms list view

Hello I have an app i'm doing in xamrian forms and I have a card styled list view. I want to be able to add 3 buttons underneath the listview one on the left one in the center and one on the right
here's my xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App.HomePage">
<ListView x:Name="listView" HasUnevenRows="true" ItemSelected="OnItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame Padding="0,0,0,8" BackgroundColor="#d2d5d7">
<Frame.Content>
<Frame Padding="15,15,15,15" OutlineColor="Gray" BackgroundColor="White">
<Frame.Content>
<StackLayout Padding="20,0,0,0" Orientation="Horizontal" HorizontalOptions="CenterAndExpand">
<Image
HorizontalOptions="StartAndExpand"
Source="{Binding Image}" />
<Label Text="{Binding Name}"
TextColor="#69add1"
FontFamily="OpenSans-Light"
FontSize="24"/>
</StackLayout>
</Frame.Content>
</Frame>
</Frame.Content>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
How would I go about doing this in xaml?
Thank's in advance! :)
Try this:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Sandbox_Forms"
x:Class="Sandbox_Forms.MainPage">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListView Grid.Row="0" BackgroundColor="Aqua">
<!-- Add bindings and data template -->
</ListView>
<StackLayout Orientation="Horizontal" Grid.Row="1">
<Button Text="Button1" HorizontalOptions="FillAndExpand"/>
<Button Text="Button2" HorizontalOptions="FillAndExpand"/>
<Button Text="Button3" HorizontalOptions="FillAndExpand"/>
</StackLayout>
</Grid>
</ContentPage>
This will limit your ListView to only fill the space that your buttons do not occupy. The output should look something like this:
<StackLayout>
<ListView>
...
</ListView>
<StackLayout Orientation="Horizontal">
<Button ... />
<Button ... />
<Button ... />
</StackLayout>
</StackLayout>

Categories