Xamarin Forms ignore Button binding from DataType on StackLayout - xaml

I have got the following xaml code:
<StackLayout Padding="10" x:DataType="model:Light">
<StackLayout HorizontalOptions="FillAndExpand" Grid.Column="0" Grid.Row="1">
<Label Text="{Binding Name}" LineBreakMode="NoWrap" Style="{DynamicResource ListItemTextStyle}" FontSize="24" HorizontalOptions="StartAndExpand" VerticalOptions="StartAndExpand"/>
</StackLayout>
<StackLayout HorizontalOptions="FillAndExpand" Grid.Column="1" Grid.Row="1" >
<Button Text="{Binding Enabled}" Command="{Binding ToggleLight}" CommandParameter="{Binding .}" HorizontalOptions="CenterAndExpand"></Button>
</StackLayout>
</StackLayout>
How do I exclude Command="{Binding ToggleLight}" on my Button form the x:DataType="model:Light" defined on my StackLayout?

Use binding-path.
Define "x:Name" outside the StackLayout (StackLayout, Grid, ListView and etc.)
Add "x:Reference" for your Command binding inside the StackLayout
The command is excluded.
Like:
<Grid x:Name="WhateverParent">
<StackLayout x:DataType="model:Light">
<Button ... Command="{Binding Path=BindingContext.ToggleLight, Source={x:Reference WhateverParent}}" />
</StackLayout>
</Grid>

Related

Keep ListView.Header anchored/sticky/frozen to top when scrolling

How to keep the built-in Header of a ListView frozen to the top when scrolling vertically down through the ListView items?
Before flagging as duplicate: I tried to apply answers in Keep ListView.HeaderTemplate visible/static/sticky in UWP for Xamarin.Forms targeting Android without success.
Short code sample:
<ListView ItemsSource="{Binding MyList}"
HasUnevenRows="True"
SeparatorVisibility="Default"
CachingStrategy="RecycleElement">
<ListView.Header>
<Label HorizontalTextAlignment="Center"
FontAttributes="Bold"
Text="Header Title"/>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding Name}"/>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Here is an alternative approach to this if the list isn't long
<StackLayout>
<Label HorizontalTextAlignment="Center"
FontAttributes="Bold"
Text="Header Title"/>
<StackLayout BindableLayout.ItemsSource="{Binding MyList}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding Name}"/>
<!-- boxview as separator -->
<BoxView HeightRequest="1" Color="Aqua" HorizontalOptions="FillAndExpand"/>
</StackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</StackLayout>

Xamarin Forms Right center checkbox

Im making an Android application and Im trying to center right checkbox on all rows in the listview, but I cant do it.
I want do something like this. Thanks
https://imgur.com/FhecIT3
<StackLayout Orientation="Vertical">
<RelativeLayout>
<ListView ItemsSource="{Binding Funcionarios}"
HasUnevenRows="True"
Margin="20"
ItemTapped="ListView_ItemTapped">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<image:CircleImage Source="{Binding Imagem}" Aspect="AspectFill" WidthRequest="60"
HeightRequest="60" BorderColor="Black" BorderThickness="2">
</image:CircleImage>
<StackLayout Orientation="Vertical">
<Label Text="{Binding Nome}" FontSize="Large"/>
<Label Text="{Binding Zona}"/>
<CheckBox IsChecked="False" />
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</RelativeLayout>
</StackLayout>
Try
<ViewCell>
<StackLayout Orientation="Horizontal">
<image:CircleImage Source="{Binding Imagem}" Aspect="AspectFill" WidthRequest="60" HeightRequest="60" BorderColor="Black" BorderThickness="2"> </image:CircleImage>
<StackLayout Orientation="Vertical">
<Label Text="{Binding Nome}" FontSize="Large"/>
<Label Text="{Binding Zona}"/>
</StackLayout>
<StackLayout Orientation="Vertical" HorizontalOptions="End">
<CheckBox IsChecked="False" VerticalOptions="Center"/>
</StackLayout>
</StackLayout>
</ViewCell>

Xamarin two labels in each end in one line

I have implemented a listview and in each item I want to have two labels, in each end horizontally. But in reality it just put the two labels next to eachother left aligned.
I read that maybe this is not possible with a stacklayout, as it doesn't take up more space than needed. (Even tried fill and fillandExpand which didn't help.)
Instead I should use a grid. But I have options on my listview, as grouping, refresh, caching, tapped, which I guess I don't have on a grid?
I would like to succeed with a listview if that is possible. Anyone have some insights to this layout issue?
Here is my xaml code:
<?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="MyApp.Page.ItemsTest">
<ListView x:Name="ItemView"
ItemsSource="{Binding ItemGroup}"
CachingStrategy="RecycleElement"
IsGroupingEnabled="true"
HasUnevenRows="True"
ItemTapped="Handle_ItemTapped">
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<StackLayout BackgroundColor="#FFA500" Orientation="Vertical" Padding="10">
<StackLayout Orientation="Horizontal">
<Label Text="{Binding Heading}" TextColor="White" FontAttributes="Bold" />
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" Padding="10" HorizontalOptions="FillAndExpand">
<Label Text="{Binding Name}" FontAttributes="Bold" HorizontalTextAlignment="Start"/>
<Label Text="{Binding Start, StringFormat='{0:HH:mm}'}" FontAttributes="Bold" HorizontalTextAlignment="End"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
Central part is this:
<StackLayout Orientation="Horizontal" Padding="10" HorizontalOptions="FillAndExpand">
<Label Text="{Binding Name}" FontAttributes="Bold" HorizontalTextAlignment="Start"/>
<Label Text="{Binding Start, StringFormat='{0:HH:mm}'}" FontAttributes="Bold" HorizontalTextAlignment="End"/>
</StackLayout>
Update:
As requested I have a colored the background of the two labels and the stacklayout. It's the same output if I use HorizontalOptions="End" and HorizontalTextAlignment="End" at the same time or each one alone. Also if I remove the HorizontalOptions="FillAndExpand" on the stacklayout, it's still the exact same graphical output. (The orange color was already present)
Maybe you could use a Grid instead of the StackLayout and place each Label in a different Column:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Text="{Binding Name}" FontAttributes="Bold" HorizontalTextAlignment="Start"/>
<Label Grid.Column="1" Text="{Binding Start, StringFormat='{0:HH:mm}'}" FontAttributes="Bold" HorizontalTextAlignment="End"/>
</Grid>
You could also use nested StackLayout
<StackLayout>
<Label />
<Label Text="Gender:" FontAttributes="Bold"/>
<StackLayout Orientation="Horizontal">
<Label HorizontalOptions="Start" Text="First Name: " FontAttributes="Bold"/>
<Entry HorizontalOptions="EndAndExpand" Placeholder="First Name" MaxLength="256" Text="{Binding FirstName}"></Entry>
</StackLayout>
</StackLayout>

Xamarin forms listview context action doesn't work with details

I use XF listview with menu context action and viewcell selected by tap.
The context actions don't work when I implemented TapGestureReconizer.
My code is here:
<ListView x:Name="PaymentCardsListView"
CachingStrategy="RecycleElement"
ItemsSource="{Binding PaymentCardsList}"
SelectedItem="{Binding SelectedPaymentCard, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Command="{Binding Path=BindingContext.EditCommand, Source={x:Reference PaymentCardsListView}"
CommandParameter="{Binding .}"
Text="Edit"/>
<MenuItem Command="{Binding Path=BindingContext.DeleteCommand, Source={x:Reference PaymentCardsListView}"
CommandParameter="{Binding .}"
IsDestructive="true"
Text="Delete"/>
</ViewCell.ContextActions>
<StackLayout Orientation="Horizontal">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=BindingContext.DetailCommand, Source={x:Reference PaymentCardsListView}"
CommandParameter="{Binding .}"/>
</StackLayout.GestureRecognizers>
<StackLayout Orientation="Vertical">
<Label Text="{Binding Name}"/>
<Label Text="{Binding Number}"/>
<StackLayout Orientation="Horizontal">
<Label Text="Expiry Date: "/>
<Label Text="{Binding ExpMonth}"/>
<Label Text="/"/>
<Label Text="{Binding ExpYear}"/>
</StackLayout>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I need to work with context menu and stacklayout tap.
How should I implement this?
It works on iOS.
The issue is only on Android.
I found confirmed bug on bugzilla.
https://bugzilla.xamarin.com/show_bug.cgi?id=46363
I'm thinking about walkthrough.
One of them it create custom renderer for view cell for android and override LongPress for display custom menu.

Set platform specific control to only one platform in xamarin forms

I have a page that contains a listview and Search bar control. There is a custom listview for android. My code as following:
<ContentPage.Content>
<ContentView>
<OnPlatform x:TypeArguments="View">
<OnPlatform.iOS>
<StackLayout Spacing="0">
<SearchBar x:Name="IosSearch"
Placeholder="Search"
TextChanged="IosSearchBar_OnTextChanged"
SearchButtonPressed="OnSearch" BackgroundColor="#19588F">
</SearchBar>
<ListView x:Name="EmpListViewIos"
ItemsSource="{Binding EmpModel.GroupedItems}"
ItemSelected="OnItemSelected"
SeparatorVisibility="Default">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="8">
<StackLayout Spacing="4" Orientation="Horizontal">
<Label Text="{Binding FullName}" FontSize="15" TextColor="Gray" LineBreakMode="NoWrap"/>
</StackLayout>
<StackLayout Spacing="4" Orientation="Horizontal">
<Label Text="{Binding Department}" FontSize="Small" TextColor="#F68933" LineBreakMode="WordWrap"/>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</OnPlatform.iOS>
<OnPlatform.Android>
<StackLayout x:Name="androidListView">
<SearchBar x:Name="DroidSearch"
Placeholder="Search"
TextChanged="DroidSearchBar_OnTextChanged"
SearchButtonPressed="OnSearch" BackgroundColor="#19588F">
</SearchBar>
<local:CustomListView x:Name="customListView"
Items="{Binding EmpModel.Items}"
VerticalOptions="FillAndExpand" MyListItemSelected="nativeListView_ItemSelected"
SeparatorColor="Black">
</local:MyListView>
</StackLayout>
</OnPlatform.Android>
<OnPlatform.WinPhone>
<StackLayout Spacing="0">
<SearchBar x:Name="WinSearch"
Placeholder="Search"
TextChanged="WinSearchBar_OnTextChanged"
SearchButtonPressed="OnSearch" BackgroundColor="#19588F">
</SearchBar>
<ListView x:Name="EmpListViewWin"
ItemsSource="{Binding EmpModel.GroupedItems}"
ItemSelected="OnItemSelected"
SeparatorVisibility="Default">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="8">
<StackLayout Spacing="4" Orientation="Horizontal">
<Label Text="{Binding FullName}" FontSize="15" TextColor="Gray" LineBreakMode="NoWrap"/>
</StackLayout>
<StackLayout Spacing="4" Orientation="Horizontal">
<Label Text="{Binding Department}" FontSize="Small" TextColor="#F68933" LineBreakMode="WordWrap"/>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</OnPlatform.WinPhone>
</OnPlatform>
</ContentView>
</ContentPage.Content>
</ContentPage>
As the representation of data is different due to that I am required custom listview for android according to it's layout defined. The above code works fine. The only problem is the redundancy, the search bar control is common for all platform but when I put the search bar control above the <ContentView> it doesn't work throws exception. Similarly the ListView is common for ios and windows only there is custom listview for android but I am forced to repeat the code for windows also same as android.
Can anyone suggest a more efficient way to achieve this. How can I apply platform specific condition only for android and common for windows and ios.
You could share the iOS and WinPhone views using a static resource:
<ContentPage>
<ContentPage.ResourceDictionary>
<StackLayout x:Key="iosOrWpView">
...
</StackLayout>
</ContentPage.ResourceDictionary>
<ContentView>
<OnPlatform x:TypeArguments="View" iOS="{StaticResource iosOrWpView}"
WinPhone="{StaticResource iosOrWpView}">
<OnPlatform.Android>
<StackLayout x:Name="androidListView">
...
</StackLayout>
</OnPlatform.Android>
</OnPlatform>
</ContentView>
<ContentPage>