Multi Data Trigger In Xamarin Forms - xamarin

I am attempting to allow click on my button ONLY if the two text fields are not null. However, I am getting the compile error of
Type multi-data trigger not found
Below is my syntax, how should I change it so it executes as desired?
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" >
<ContentPage.Content>
<StackLayout Orientation="Vertical" Padding="30" Spacing="40">
<BoxView HeightRequest="10"/>
<Frame BackgroundColor="#BF043055" HasShadow="False">
<StackLayout Orientation="Vertical" Spacing="10">
<Entry x:Name="Email" Text="{Binding Email}" Placeholder="Email"
PlaceholderColor="Red" HeightRequest="50"
Keyboard="Email" TextColor="Black" />
<Entry x:Name="Password" Text="{Binding Password}" Placeholder="Password"
PlaceholderColor="Red" HeightRequest="50"
IsPassword="True" TextColor="Black" />
</StackLayout>
</Frame>
<Button x:Name="loginbutton" Command="{Binding SubmitCommand}" Text="Login" TextColor="White"
FontAttributes="Bold" FontSize="Large" HorizontalOptions="FillAndExpand"
BackgroundColor="#088da5" >
<Button.Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=Email, Path=Text.Length, Mode=OneWay}" Value="0"/>
<Condition Binding="{Binding ElementName=Password, Path=Text.Length, Mode=OneWay}" Value="0"/>
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="False"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</StackLayout>
</ContentPage.Content>
</ContentPage>
EDIT
I edited my syntax to the below but I am getting a compile error of:
No property, bindable property, or event found for 'ElementName', or mismatching type between value and property.
<Button x:Name="loginbutton" Command="{Binding SubmitCommand}" Text="Login" TextColor="White"
FontAttributes="Bold" FontSize="Large" HorizontalOptions="FillAndExpand"
BackgroundColor="#088da5" >
<Button.Style>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<MultiTrigger TargetType="{x:Type Button}">
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=Email, Path=Text.Length, Mode=OneWay}" Value="0"/>
<Condition Binding="{Binding ElementName=Password, Path=Text.Length, Mode=OneWay}" Value="0"/>
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="False"/>
</MultiTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>

MultiDataTrigger is specific to WPF. Xamarin uses MultiTrigger, which essentially does the same thing. Have a look through this blog post to see how to implement Triggers in Xamarin Forms.

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.

Passing button value as command parameter

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" />

Xamarin.Forms - Label not centered

I've got a StackView which contains 2 Labels. One is normal text, and the other one is a FontAwesome Icon.
Anyhow both Labels are not centered vertically inside the StackView. Here is the Code for them:
The Styles:
<Style x:Key="FAIconedLabel" TargetType="Label">
<Setter Property="TextColor" Value="White"/>
<Setter Property="FontSize" Value="40" />
<Setter Property="Margin" Value="0" />
</Style>
<Style x:Key="EmailLabel" TargetType="Label">
<Setter Property="TextColor" Value="White"/>
<Setter Property="FontSize" Value="20" />
</Style>
And the Views itself
<!-- Top Right -->
<Grid BackgroundColor="{StaticResource LamaControlGray}"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent,
Property=Width,Factor=1,Constant=-400}"
RelativeLayout.WidthConstraint="{ConstraintExpression
Type=RelativeToParent,Property=Width,Factor=0,Constant=400}"
RelativeLayout.HeightConstraint="{ConstraintExpression
Type=RelativeToParent,Property=Height,Factor=0,Constant=40}" >
<StackLayout Orientation="Horizontal" HorizontalOptions="End" VerticalOptions="FillAndExpand" BackgroundColor="Red">
<Label x:Name="LblUserEmail" Margin="0,0,10,0" Text="{Binding UserEmail}" VerticalOptions="FillAndExpand" Style="{StaticResource EmailLabel}"/>
<fal:FontAwesomeLabel Text="{Binding SettingsIcon}" BackgroundColor="Green" VerticalOptions="CenterAndExpand" Style="{StaticResource FAIconedLabel}" />
</StackLayout>
</Grid>
Do I miss something here?
Edit 1
I added a BackgroundColor to see, if the Label actually fills the StackView
Edit 2
After cleaning and rebuilding the solution, the email Label is centered now. But the Iconed one still remains at the bottom
Yes you are missing something.
You're not setting it to be centered vertically.
Either
<Label x:Name="LblUserEmail" Margin="0,0,10,0" Text="{Binding UserEmail}" VerticalOptions="FillAndExpand" VerticalTextAlignment="Center" Style="{StaticResource EmailLabel}"/>
or
<Label x:Name="LblUserEmail" Margin="0,0,10,0" Text="{Binding UserEmail}" VerticalOptions="CenterAndExpand" Style="{StaticResource EmailLabel}"/>

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