Passing button value as command parameter - xamarin

I have a calculator style grid. How can I pass the text of the button as a Command Parameter in Xamarin Forms:
CONTENT RESOURCE
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="PhoneKeys" TargetType="Button">
<Setter Property="BackgroundColor" Value="White"/>
<Setter Property="FontSize" Value="36"/>
<Setter Property="Command" Value="{Binding Source={x:Reference contactsListView}, Path=BindingContext.TapCommand1}"/>
<Setter Property="CommandParameter" Value="Pass Button Text"/>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
GRID LAYOUT
<Button Style="{StaticResource PhoneKeys}" Text="1" Grid.Row="1" Grid.Column="0" />
<Button Style="{StaticResource PhoneKeys}" Text="1" Grid.Row="1" Grid.Column="0" />
<Button Style="{StaticResource PhoneKeys}" Text="2" Grid.Row="1" Grid.Column="1" />
<Button Style="{StaticResource PhoneKeys}" Text="3" Grid.Row="1" Grid.Column="2" />
<Button Style="{StaticResource PhoneKeys}" Text="4" Grid.Row="2" Grid.Column="0" />
<Button Style="{StaticResource PhoneKeys}" Text="5" Grid.Row="2" Grid.Column="1" />
<Button Style="{StaticResource PhoneKeys}" Text="6" Grid.Row="2" Grid.Column="2" />
<Button Style="{StaticResource PhoneKeys}" Text="7" Grid.Row="3" Grid.Column="0" />
<Button Style="{StaticResource PhoneKeys}" Text="8" Grid.Row="3" Grid.Column="1" />
<Button Style="{StaticResource PhoneKeys}" Text="9" Grid.Row="3" Grid.Column="2" />
<Button Style="{StaticResource PhoneKeys}" Text="*" Grid.Row="4" Grid.Column="0" />
<Button Style="{StaticResource PhoneKeys}" Text="0" Grid.Row="4" Grid.Column="1" />
<Button Style="{StaticResource PhoneKeys}" Text="#" Grid.Row="4" Grid.Column="2" />

Use this syntax to get property of control "{x:Reference myButton}"
You can send self button reference to get complete button object
Style
<Setter Property="CommandParameter" Value="{x:Reference myButton}" />
XAML
<Button x:Name="myButton" Style="{StaticResource PhoneKeys}" Text="#" Grid.Row="4" Grid.Column="2" />
Define button name of each button and get the object reference of that button.
public ICommand TapCommand1 => new Command((obj) =>
{
var button = obj as Button;
var text = button.Text;
});
OR Best way to define command parameter in each button with every button name
<Button x:Name="myButton" Style="{StaticResource PhoneKeys}" CommandParameter="{x:Reference myButton}" Text="#" Grid.Row="4" Grid.Column="2" />

Related

Xamarin how to position label to right align screen in listview

I'm learning xamarin and all my attempts to influence the behavior of my label have failed. only my label still behaves strangely how to right align screen.
They do not change even if I put horizontalOptions everywhere, it seems to me that I just don’t know something
my ProductCard
<Grid xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:models="clr-namespace:Notes.Models;assembly=Notes"
x:DataType="models:Goods"
x:Class="Notes.Cells.ProductCard">
<Frame Style="{StaticResource ProductCard}" BackgroundColor="Coral">
<StackLayout Orientation="Horizontal">
<StackLayout VerticalOptions="Center">
<Label
BackgroundColor="Aqua"
HorizontalTextAlignment="End"
VerticalOptions="End"
HorizontalOptions="End">
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding Name}" Style="{StaticResource LabelMedium}" BackgroundColor="Blue"></Span>
<Span Text=" " BackgroundColor ="Brown"/>
<Span Text="Price: " BackgroundColor="Green"/>
<Span Text="{Binding Price}" FontAttributes="Bold" BackgroundColor="Yellow"/>
</FormattedString>
</Label.FormattedText>
</Label>
</StackLayout>
</StackLayout>
</Frame>
and my ListView
<?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:viewmodels="clr-namespace:Notes.ViewModel"
xmlns:cells="clr-namespace:Notes.Cells"
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
x:DataType="viewmodels:GoodsViewModel"
x:Class="Notes.Views.ProductsCatalog"
>
<ContentPage.BindingContext>
<viewmodels:GoodsViewModel />
</ContentPage.BindingContext>
<ContentPage.Resources>
<ResourceDictionary>
<DataTemplate x:Key="Normal">
<ViewCell>
<cells:ProductCard/>
</ViewCell>
</DataTemplate>
<DataTemplate x:Key="Special">
<ViewCell>
<cells:SpecialItem/>
</ViewCell>
</DataTemplate>
<cells:ItemDataTemplateSelector x:Key="GoodsSelector"
Normal="{StaticResource Normal}"
Special="{StaticResource Special}"/>
</ResourceDictionary>
</ContentPage.Resources>
<ListView
SeparatorVisibility="Default"
CachingStrategy="RecycleElement"
Style="{StaticResource NoteNewsListView}"
GroupDisplayBinding="{Binding Key}"
IsGroupingEnabled="True"
IsRefreshing="{Binding IsBusy, Mode=OneWay}"
SelectedItem="{Binding CurrentGoods, Mode=TwoWay}"
ItemsSource="{Binding GoodsGroup}"
RefreshCommand="{Binding RefreshCommand}"
ItemTemplate="{StaticResource GoodsSelector}">
<ListView.Behaviors>
<xct:EventToCommandBehavior
Command="{Binding SelectedCommand}"
EventName="ItemSelected" />
</ListView.Behaviors>
<ListView.GroupHeaderTemplate>
<DataTemplate x:DataType="{x:Null}">
<ViewCell>
<StackLayout Padding="0,0,0,0" Margin="10,0,0,0">
<Label Style="{StaticResource LabelLarge}" Text="{Binding Key}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.Header>
<StackLayout Orientation="Horizontal">
<Label
Margin="80"
FontFamily="AC"
HorizontalOptions="Center"
Style="{StaticResource LabelLarge}"
Text="Catalog Products">
</Label>
</StackLayout>
</ListView.Header>
<ListView.Footer>
<StackLayout HorizontalOptions="Center" Orientation="Horizontal">
<Button
Command="{Binding LoadMoreCommand}"
Style="{StaticResource ButtonOutline}"
Text="Load more" />
</StackLayout>
</ListView.Footer>
</ListView>
and my styles
<Style x:Key="ServiceCard" TargetType="Frame">
<Setter Property="HasShadow"
Value="{OnPlatform Android=true, iOS=false, Default=true}"/>
<Setter Property="CornerRadius" Value="20"/>
<Setter Property="BackgroundColor"
Value="{AppThemeBinding Dark={StaticResource CardBackgroundDark},
Light={StaticResource CardBackground}}"/>
</Style>
<Style x:Key="NoteNewsListView" TargetType="ListView">
<Setter Property="HasUnevenRows" Value="True"/>
<Setter Property="BackgroundColor" Value="Transparent"/>
<Setter Property="SeparatorVisibility"
Value="None"/>
<Setter Property="RefreshControlColor"
Value="{StaticResource SystemBlue}"/>
<Setter Property="IsPullToRefreshEnabled"
Value="True"/>
</Style>
how to do like below picture?
thanks #Jason for advice to add backgroundcolor to my labels
We can create two Labels to display Name and Price.
<Grid xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:models="clr-namespace:Notes.Models;assembly=Notes"
x:DataType="models:Goods"
x:Class="Notes.Cells.ProductCard">
<Frame Style="{StaticResource ProductCard}" BackgroundColor="Coral">
<StackLayout Orientation="Horizontal">
<Label
BackgroundColor="Aqua"
HorizontalTextAlignment="Start"
HorizontalOptions="FillAndExpand">
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding Name}" Style="{StaticResource LabelMedium}" BackgroundColor="Blue"></Span>
</FormattedString>
</Label.FormattedText>
</Label>
<Label HorizontalOptions="End">
<Label.FormattedText>
<FormattedString>
<Span Text="Price: " BackgroundColor="Green"/>
<Span Text="{Binding Price}" FontAttributes="Bold" BackgroundColor="Yellow"/>
</FormattedString>
</Label.FormattedText>
</Label>
</StackLayout>
</Frame>

I want to change the shape of the radio button, can I change the border size?

<ContentPage.Resources>
<ControlTemplate x:Key="FrameRadioTemplate">
<Frame
Padding="10"
BackgroundColor="{DynamicResource ColorBorder000}"
BorderColor="Red"
HeightRequest="50"
WidthRequest="130">
<ContentPresenter>
<ContentPresenter.Resources>
<Style TargetType="Label">
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="VerticalOptions" Value="Center" />
<Style.Triggers>
<DataTrigger
Binding="{Binding Path=IsChecked, Source={x:RelativeSource AncestorType={x:Type RadioButton}}}"
TargetType="Label"
Value="True">
<Setter Property="TextColor" Value="{DynamicResource ColorText111}" />
<Setter Property="FontAttributes" Value="Bold" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CheckedStates">
<VisualState x:Name="Checked">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="{DynamicResource ColorBack004}" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Unchecked">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="{DynamicResource ColorBack000}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Frame>
</ControlTemplate>
</ContentPage.Resources>
<StackLayout
x:Name="xDispContents"
Grid.Row="9"
Grid.Column="1"
HorizontalOptions="StartAndExpand"
Orientation="Horizontal"
Spacing="0">
<Ctrl:CtrlRadioButton
x:Name="xBtnDisp_ABS"
ControlTemplate="{StaticResource FrameRadioTemplate}"
HorizontalOptions="Center"
VerticalOptions="Center">
<Ctrl:CtrlRadioButton.Content>
<!--<Label TextColor="{DynamicResource ColorText000}" />-->
<Ctrl:CtrlButton Text="ABS" />
</Ctrl:CtrlRadioButton.Content>
</Ctrl:CtrlRadioButton>
<Ctrl:CtrlRadioButton
x:Name="xBtnDisp_Trans"
ControlTemplate="{StaticResource FrameRadioTemplate}"
HorizontalOptions="Center"
VerticalOptions="Center">
<Ctrl:CtrlRadioButton.Content>
<Label Text="%T" TextColor="{DynamicResource ColorText000}" />
</Ctrl:CtrlRadioButton.Content>
</Ctrl:CtrlRadioButton>
</StackLayout>
I want to change the shape of the radio button, can I change the border size?
I'm trying to change the shape of a radio button's appearance using a control template. But I want to change the border thickness of the frame, but there is no way.
The default thickness is too thick. I've looked for many other examples, but there's no information about the thickness, so I'm asking.
Maybe you can use this , Frame in a Frame .
Change the Padding for the "BorderWith" Color.
<Frame HeightRequest="50" WidthRequest="100" BackgroundColor="Red" HorizontalOptions="Center" VerticalOptions="Start" Padding="0.7" IsClippedToBounds="True">
<Frame HeightRequest="50" WidthRequest="100" BackgroundColor="White" HorizontalOptions="Center" VerticalOptions="Start" Margin="0" Padding="0" IsClippedToBounds="True">
<Label Text="Padding 0.7" HorizontalOptions="Center" />
</Frame>
</Frame>
<Frame HeightRequest="50" WidthRequest="100" BackgroundColor="Red" HorizontalOptions="Center" VerticalOptions="Start" Padding="1" IsClippedToBounds="True">
<Frame HeightRequest="50" WidthRequest="100" BackgroundColor="White" HorizontalOptions="Center" VerticalOptions="Start" Margin="0" Padding="0" IsClippedToBounds="True">
<Label Text="Padding 1" HorizontalOptions="Center" />
</Frame>
</Frame>
<Frame HeightRequest="50" WidthRequest="100" BackgroundColor="Red" HorizontalOptions="Center" VerticalOptions="Start" Padding="5" IsClippedToBounds="True">
<Frame HeightRequest="50" WidthRequest="100" BackgroundColor="White" HorizontalOptions="Center" VerticalOptions="Start" Margin="0" Padding="0" IsClippedToBounds="True">
<Label Text="Padding 5" HorizontalOptions="Center" />
</Frame>
</Frame>
The result a border in Red in different size.

Highlight Selected Item in CollectionView in Xamarin Forms

I am trying to hightlight selected item of collectionview with different color. The code works fine in iOS, but in Android it doesn't work. In Android, the first item is always selected but it doesn't hightlight the other items when I click them.
Update
I found the issue is GestureRecognizers on the Grid, If I remove that. It behavious as expected. After adding GestureRecognizers, the expected behavior is lost.
Workaround
If I wrap the Grid inside SwipeView, it works fine. However, the problem still remain when CollectionView has more than 100 items.
2nd Workaround
This worked nicely for any number of items in the CollectionView. Add second Grid inside the 1st Grid and apply GestureRecognizers event on the 2nd Grid and everythings works smoothly and as expected.
Theme.xaml -> getting styles from the theme file
<Style TargetType="Grid" x:Key="ItemTemplateGrid">
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup>
<VisualState Name="Normal"/>
<VisualState Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="{AppThemeBinding Dark={StaticResource BackgroundSecondaryColorDark}, Light={StaticResource BackgroundSecondaryColorLight}}"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
XAML Page Resource
<DataTemplate x:Key="AndroidAyaItemTemplate">
<Grid RowDefinitions="*,Auto" Style="{DynamicResource ItemTemplateGrid}">
<Grid Grid.Row="0" RowDefinitions="Auto,Auto,Auto" RowSpacing="0" Padding="10">
<Label Grid.Row="0" LineBreakMode="WordWrap" IsVisible="{Binding BindingContext.ShowEnglishVerseNumber,
Source={x:Reference MyPage}, Converter={StaticResource InverterBooleanConverter}}">
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding ArabicText.Aya}" FontSize="{Binding BindingContext.ActiveArabicFont.FontSize, Source={x:Reference MyPage}}"
FontFamily="{Binding BindingContext.ActiveArabicFont.FontPath, Source={x:Reference MyPage}}"/>
<Span Text="{Binding ArabicText.ArabicAyaNumber, StringFormat='﴿{0}﴾'}"
FontSize="{Binding BindingContext.ActiveArabicFont.FontSize, Source={x:Reference MyPage}}"
FontFamily="Sherzad"></Span>
</FormattedString>
</Label.FormattedText>
</Label>
<Label Grid.Row="0" LineBreakMode="WordWrap" IsVisible="{Binding BindingContext.ShowEnglishVerseNumber, Source={x:Reference MyPage}}">
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding ArabicText.Aya}" FontSize="{Binding BindingContext.ActiveArabicFont.FontSize, Source={x:Reference MyPage}}"
FontFamily="{Binding BindingContext.ActiveArabicFont.FontPath, Source={x:Reference MyPage}}"/>
<Span Text="﴿" FontSize="35" FontFamily="Sherzad"></Span>
<Span Text="{Binding ArabicText.AyaNumber, Converter={StaticResource ZeroToEmptyConverter}}" FontSize="Small"></Span>
<Span Text="﴾" FontSize="35" FontFamily="Sherzad"></Span>
</FormattedString>
</Label.FormattedText>
</Label>
<Label Grid.Row="1" LineBreakMode="WordWrap" HorizontalTextAlignment="Start" Margin="0,5,0,5"
IsVisible="{Binding BindingContext.ShowTransliteration, Source={x:Reference MyPage}}"
FontSize="{Binding BindingContext.TransliterationFontSize, Source={x:Reference MyPage}}"
Text="{Binding ArabicText.Transliteration}"
FlowDirection="LeftToRight">
</Label>
<Label Grid.Row="2" LineBreakMode="WordWrap" HorizontalTextAlignment="Start"
IsVisible ="{Binding BindingContext.TranslationVisible, Source={x:Reference MyPage}}"
FontSize="{Binding BindingContext.ActiveTranslationFont.FontSize, Source={x:Reference MyPage}}"
FontFamily="{Binding BindingContext.ActiveTranslationFont.FontPath, Source={x:Reference MyPage}}"
Text="{Binding AyaTranslation}"
FlowDirection="{Binding BindingContext.ActiveTranslationLanguage.FlowDirection, Source={x:Reference MyPage}}"/>
</Grid>
<BoxView Grid.Row="1" Style="{DynamicResource HLine}" IsVisible="{Binding BindingContext.ShowHorizentalLine, Source={x:Reference MyPage}}"/>
<Grid.GestureRecognizers>
<TapGestureRecognizer NumberOfTapsRequired="2" Command="{Binding BindingContext.ShareAyaCommand,Source={x:Reference itemView}}" CommandParameter="{Binding .}"/>
<SwipeGestureRecognizer Direction="Right" Command="{Binding BindingContext.NextChapterCommand, Source={x:Reference MyPage}}"/>
<SwipeGestureRecognizer Direction="Left" Command="{Binding BindingContext.PreviousChapterCommand, Source={x:Reference MyPage}}"/>
</Grid.GestureRecognizers>
</Grid>
</DataTemplate>
CollectionView
<CollectionView Grid.Row="0" ItemsSource="{Binding ArabicListText}" SelectedItem="{Binding SelectedAya}" SelectionMode="Single" FlowDirection="RightToLeft"
ItemTemplate="{StaticResource AndroidAyaItemTemplate}"
x:Name="itemView">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Vertical" ItemSpacing="5"/>
</CollectionView.ItemsLayout>
</CollectionView>
If I remove the style "ItemTemplateGrid" from the Grid, it highlights every row accordingly, but the color is the default color of OS.
There is no need for SwipeView. It should work without boths workarounds.
Since you had used the SelectedItem="{Binding SelectedAya}" , you could define a property in the model which bind the backgroundcolor of the DataTemplate so that you don't need to use style dictionary any more .
in your model
Add a property
private Color bgColor;
public Color BgColor
{
get => bgColor;
set
{
if (bgColor!= value)
{
bgColor= value;
foreach(YourModel model in ArabicListText)
{
if(mdoel == SelectedAya)
{
if(App.Current.RequestedTheme== OSAppTheme.Dark)
{
model.BgColor = xxx;
}
else
{
model.BgColor = xxx;
}
}
else
{
model.BgColor = xxx;
}
}
OnPropertyChanged(nameof(BgColor));
}
}
}
in DataTemplate
<Grid RowDefinitions="*,Auto" BackgroundColor="{Binding BgColor}" Padding="10">
in Code Behind(ViewModel)
private YourModel selectedAya;
public YourModel SelectedAya
{
get => selectedAya;
set
{
if (selectedAya!= value)
{
selectedAya= value;
OnPropertyChanged(nameof(SelectedAya));
}
}
}

I am using a label as a button. How can I surround it with a border with round edges?

Here is the code that I am using with Xamarin Forms:
<Grid Grid.Column="0" ColumnSpacing="0" Margin="0,0,10,0">
<Label Grid.Column="0" x:Name="faveIconLabel" Style="{StaticResource mediumIcon}" Margin="0,2,0,0" HorizontalOptions="Fill" FontFamily="FontAwesome" VerticalOptions="Center" VerticalTextAlignment="Center" />
<Label Grid.Column="1" x:Name="hiddenIconLabel" Style="{StaticResource mediumIcon}" Margin="0,2,0,0" HorizontalOptions="Fill" FontFamily="FontAwesome" VerticalOptions="Center" VerticalTextAlignment="Center" />
</Grid>
Can someone help and let me know how I can surround these two labels with a border to make them as much as possible look like buttons.
Frame can be used for this very purpose:
<Grid Grid.Column="0" ColumnSpacing="0" Margin="0,0,10,0">
<Frame Grid.Column="0" CornerRadius="5" OutlineColor="Black">
<Label x:Name="faveIconLabel" Style="{StaticResource mediumIcon}" Margin="0,2,0,0" HorizontalOptions="Fill" FontFamily="FontAwesome" VerticalOptions="Center" VerticalTextAlignment="Center" />
</Frame>
<Frame Grid.Column="1" CornerRadius="5" OutlineColor="Black">
<Label x:Name="hiddenIconLabel" Style="{StaticResource mediumIcon}" Margin="0,2,0,0" HorizontalOptions="Fill" FontFamily="FontAwesome" VerticalOptions="Center" VerticalTextAlignment="Center" />
</Frame>
</Grid>

Behaviours and Triggers

I have a simple login form with two fields username and pass. Using behaviours I implemented email validation (not empty, valid email) and pass validation (not empty)
<StackLayout Padding="30" VerticalOptions="CenterAndExpand" Spacing="15">
<Entry Text="{Binding Email}" Keyboard="Email" IsEnabled="{Binding IsNotBusy}" Placeholder="Email address">
<Entry.Behaviors>
<local:EntryValidatorBehavior IsCheckEmail="true" ValidateFromStart="false" IsCheckEmpty="true" x:Name="emailValidator" />
</Entry.Behaviors>
</Entry>
<Label Text="{Binding Source={x:Reference emailValidator}, Path=Message}" />
<Entry Text="{Binding Password}" IsPassword="true" IsEnabled="{Binding IsNotBusy}" Placeholder="Password">
<Entry.Behaviors>
<local:EntryValidatorBehavior ValidateFromStart="false" IsCheckEmpty="true" x:Name="passwordValidator">
</local:EntryValidatorBehavior>
</Entry.Behaviors>
</Entry>
<Label Text="{Binding Source={x:Reference passwordValidator}, Path=Message}" />
<StackLayout Orientation="Horizontal">
<Button Text="Forgot Password?" Command="{Binding ForgotButton}" TextColor="White" HeightRequest="40" VerticalOptions="End">
</Button>
<Button HorizontalOptions="EndAndExpand" Text="Sign In" Command="{Binding LoginButton}" TextColor="White" BackgroundColor="#f50057" HeightRequest="40" WidthRequest="100">
</Button>
</StackLayout>
</StackLayout>
This works perfectly, but at the bottom of the form I have a Login button which should be hidden as long as both email and password are not valid.
How can this be implemented? I was thinking by using Triggers
<Button HorizontalOptions="EndAndExpand" Text="Sign In" Command="{Binding LoginButton}" TextColor="White" BackgroundColor="#f50057" HeightRequest="40" WidthRequest="100" IsVisible="false">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<MultiTrigger TargetType="Button">
<MultiTrigger.Conditions>
<BindingCondition Binding="{Binding Source={x:Reference emailValidator}, Path=IsValid}" Value="True" />
<BindingCondition Binding="{Binding Source={x:Reference passwordValidator}, Path=Text.IsValid}" Value="True" />
</MultiTrigger.Conditions>
<Setter Property="IsVisible" Value="True" />
</MultiTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
but this doesn't work.
Thanks in advance!

Resources