Change the style class of element conditionally in Xamarin - xamarin.forms

I'm trying to change the class of a Frame depending on a variable value.
I tried changing the "class", "ClassId" and "StyleClass" properties.
I also tried with triggers, but finally I had to change it this way.
Is there any way to do it more elegant? What if I need to change more styles conditionally?
I tried this:
<Frame x:Name="FilaListaEventos" class="{Binding Alerts}">
And this:
<Frame x:Name="FilaListaEventos" StyleClass="{Binding Alerts}">
And this:
<Frame x:Name="FilaListaEventos" ClassId="{Binding Alerts}">
And also tried this:
<Frame StyleClass="ListRow">
<Frame.Triggers>
<DataTrigger TargetType="Frame" Binding="{Binding Alerts}" Value="True">
<Setter Property="ClassId" Value="ListRowAlerts" />
</DataTrigger>
</Frame.Triggers>
...
But finally I got it this way:
<Frame StyleClass="ListRow">
<Frame.Triggers>
<DataTrigger TargetType="Frame" Binding="{Binding Alerts}" Value="True">
<Setter Property="BackgroundColor" Value="Yellow" />
</DataTrigger>
</Frame.Triggers>
...

Sorry that you had to wait two years, but this is how I did it.
<Style.Triggers>
<DataTrigger TargetType="Frame" Binding="{Binding Source={x:Static Your Property}}" Value="Required Value">
<Setter Property="YourProperty" Value="YourValue"/>
</DataTrigger>
</Style.Triggers>

Related

How do I trigger a Maui DataTrigger on load

I have a DataTrigger to set some styling based on the result of a validation (it is linked to a TextValidationBehaviour). It works fine, except I want it to trigger when the page loads so the user can see what they need to fill in (i.e. Entry is red until the user types something into it).
So is there any way to trigger the validation on page load?
Here is my code, but open to suggestions:
<Frame WidthRequest="350">
<StackLayout Orientation="Horizontal">
<Entry Style="{StaticResource Key=EntryInverted}" Placeholder="Last Name" Text="{Binding LastName}">
<Entry.Behaviors>
<toolkit:TextValidationBehavior x:Name="LastNameVal"
InvalidStyle="{StaticResource InvalidEntryStyle}"
Flags="ValidateOnValueChanged"
MinimumLength="2"
MaximumLength="99" />
</Entry.Behaviors>
</Entry>
</StackLayout>
<Frame.Style>
<Style TargetType="Frame" BasedOn="{StaticResource Key=EntryFrame}">
<Setter Property="BorderColor" Value="White"/>
<Style.Triggers>
<DataTrigger TargetType="Frame" Binding="{Binding Source={x:Reference LastNameVal}, Path=IsNotValid}" Value="True">
<Setter Property="BorderColor" Value="{StaticResource FrameErrorBorder}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Frame.Style>
</Frame>
You can add a trigger to the entry, such as:
<Entry >
<Entry.Triggers>
<MultiTrigger TargetType="Entry">
<MultiTrigger.Conditions>
<PropertyCondition Property="IsFocused" Value="false"/>
<PropertyCondition Property="Text" Value="{x:Null}"/>
</MultiTrigger.Conditions>
<Setter Property="BackgroundColor" Value="Red"/>
</MultiTrigger>
</Entry.Triggers>
</Entry>
The codes above will make the entry's background color show as red. And it will show the default background color when user taps the entry.
Or you want to the entry is red if the entry has no text in it. You can try the following code:
<Entry >
<Entry.Triggers>
<MultiTrigger TargetType="Entry">
<MultiTrigger.Conditions>
<BindingCondition Binding="{Binding Source={RelativeSource Self}, Path= Text.Length}" Value="0"/>
</MultiTrigger.Conditions>
<Setter Property="BackgroundColor" Value="Red"/>
</MultiTrigger>
<Trigger TargetType="Entry" Property="Text" Value="{x:Null}">
<Setter Property="BackgroundColor" Value="Red"/>
</Trigger>
</Entry.Triggers>
</Entry>
When you use the trigger above, the entry will be red until it has been typed something.

Is it possible to replace/modify Implicit style at run time xamarin forms

I have the need to replace at runtime an implicit style that is located in a merged resource dictionary
for example lets suppose I have
<Style TargetType="Label">
<Setter Property="FontSize" Value="14" />
</Style>
Now I want to replace the all style with something else at runtime. Can this be done?
Above is just a sample.. Nothing todo with theming or anything else, I have the need to replace the all implicit style at runtime.
Can I detect based on TargetType ?
thanks
If I understand your problem correctly, I think that data triggers might help you. For example, you can change FontSize with something like this:
<Style x:Key="labelStyle" TargetType="Label">
<Setter Property="FontSize" Value="14" />
<Style.Triggers>
<DataTrigger TargetType="Label" Binding="{Binding isSmallDevice}" Value="True">
<Setter Property="FontSize" Value="10" />
</DataTrigger>
</Style.Triggers>
</Style>
Actually in this occasion I need to change some fontsizes at runtime based on whether is a small device or not
You can use OnIdiom markup extension to detect Phone or Table or desktop.
<Label Text="Welcome to Xamarin.Forms!">
<Label.Style>
<Style TargetType="Label">
<Setter Property="FontSize">
<Setter.Value>
<OnIdiom
x:TypeArguments="x:Double"
Phone="18"
Tablet="50" />
</Setter.Value>
</Setter>
</Style>
</Label.Style>
</Label>

Set DatePicker text color according to IsEnabled property

In one of my Xamarin.Forms apps I want to change the text color of a DatePicker according to the IsEnabled property.
I tried two known ways:
1) Using a style
In App.xaml:
<Style x:Key="DatePickerStyle" TargetType="DatePicker">
<Style.Triggers>
<Trigger TargetType="DatePicker" Property="IsEnabled" Value="True">
<Setter Property="TextColor" Value="Blue" />
</Trigger>
<Trigger TargetType="DatePicker" Property="IsEnabled" Value="False">
<Setter Property="TextColor" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
In View.xaml:
<DatePicker IsEnabled="{Binding IsEnabled}" Style="{StaticResource DatePickerStyle}" ... />
2) Adding the trigger in XAML
<ViewCell>
<DatePicker IsEnabled="{Binding IsEnabled}" ...>
<DatePicker.Triggers>
<Trigger TargetType="DatePicker" Property="IsEnabled" Value="True">
<Setter Property="TextColor" Value="Blue" />
</Trigger>
<Trigger TargetType="DatePicker" Property="IsEnabled" Value="False">
<Setter Property="TextColor" Value="Red" />
</Trigger>
</DatePicker.Triggers>
</DatePicker>
</ViewCell>
Both ways lead to a "System.InvalidOperationException: bindable not an instance of AssociatedType" exception.
Is it possible to change the text color of a picker with an applied style that contains a trigger at the IsEnabled property? Will a behavior be a better way to go?
I faced a similar issue with DatePicker and found no explanation on Xamarin forums or msdn. I have finally used the following workaround and it works
<Style TargetType="DatePicker">
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList x:Name="CommonStates">
<VisualStateGroup>
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="LightGray" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
See also Visual State Manager.

How to write the Style for check box place in the GridCell UWP?

enter image description here
I have tried to write the style for check box placed in the Grid cell by setting the target type as checkbox, but its apply the style also for the filter checkbox. could anybody suggest me to write the style only for the Grid cell check box.
Please find the image attached above i have write a style only for the checkbox loaded in the grid cell instead of the applying to all
I tried it by this way
<Page.Resources>
<Style TargetType="CheckBox">
<Setter Property="Background" Value="Red"/>
</Style>
</Page.Resources>
<Page.DataContext>
<local:ViewModel/>
</Page.DataContext>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<my:SfDataGrid ItemsSource="{Binding Orders}" AllowFiltering="True" />
</Grid>
You have to use Column property of DataGridCell and check its DisplayIndex value and write a DataTrigger.
Sample approach :
<DataGrid ...>
<DataGrid.Resources>
<Style TargetType="CheckBox">
<Setter Property="Background" Value="Green"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Column.DisplayIndex, RelativeSource={RelativeSource AncestorType=DataGridCell, Mode=FindAncestor}}" Value="0">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
</DataGrid>
Ok. #BalamuruganR I've made a simple code sample for you. Using the GridTemplateColumn and specify a "x:Key" for your custom style. Please check the following code sample:
<Page.Resources>
<Style x:Key="CheckBoxStyle1" TargetType="CheckBox">
<Setter Property="Background" Value="Red" />
</Style>
<DataTemplate x:Key="cellTemplate">
<CheckBox Content="DataGrid" IsChecked="{Binding Flag}" Style="{StaticResource CheckBoxStyle1}"></CheckBox>
</DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<syncfusion:SfDataGrid x:Name="sfGrid" Grid.Column="0"
AllowGrouping="True"
AutoExpandGroups="True"
ShowGroupDropArea="True"
AllowEditing="True"
AllowFiltering="True"
AutoGenerateColumns="False"
ItemsSource="{Binding UserDetails}">
<syncfusion:SfDataGrid.Columns>
<syncfusion:GridTextColumn MappingName="UserId" />
<syncfusion:GridTextColumn MappingName="Name" />
<syncfusion:GridDateTimeColumn MappingName="DateofBirth" />
<syncfusion:GridNumericColumn MappingName="ContactNo" />
<syncfusion:GridTemplateColumn MappingName="Flag" CellTemplate="{StaticResource cellTemplate}" />
</syncfusion:SfDataGrid.Columns>
</syncfusion:SfDataGrid>
</Grid>

Is there a clean way to implement ancestor style triggers in XAML WPF

I'm creating some styles for a basic property grid. The XAML for an example would be
<StackPanel Style="{StaticResource propertyGrid}" Orientation="Vertical" >
<ItemsControl Tag="property">
<Label>Nodes</Label>
<TextBox Text="{Binding Nodes}"/>
</ItemsControl>
<ItemsControl Tag="property">
<Label >Major Diameter</Label>
<TextBox Text="{Binding MajorDiameter}"/>
</ItemsControl>
<ItemsControl Tag="property">
<Label>Minor Diameter</Label>
<TextBox Text="{Binding MinorDiameter}"/>
</ItemsControl>
<ItemsControl Tag="property">
<Label>Excenter</Label>
<TextBox Text="{Binding Excenter}"> </TextBox>
</ItemsControl>
</StackPanel>
and my styling follows this logic. Labels or TextBoxes within
an ItemsControl with Tag property get special styling. If I
was doing this as psuedo CSS I'd write
ItemsControl.property Label {
Grid.Row: 0;
FontWeight: bold;
Padding:0,4,0,0;
}
ItemsControl.property TextBox {
Grid.Row: 1;
FontWeight: bold;
}
after much teeth gnashing I figured out one way to do this and this
was to use DataTriggers to look back up the tree rather than the
CSS mentality to look down the tree. However I'm rather horrified
by the verbosity of it. See below.
<Style TargetType="StackPanel" x:Key="propertyGrid">
<Style.Resources>
<Style TargetType="Label">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}, Path=Tag}" Value="property">
<Setter Property="Grid.Row" Value="0"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Padding" Value="0,4,0,0"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}, Path=Tag}" Value="property">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Grid.Row" Value="1"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="ItemsControl" x:Key="property">
<Style.Triggers>
<Trigger Property="Tag" Value="property">
<Setter Property="Focusable" Value="False"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<Grid Width="Auto">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
</Grid>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Style.Resources>
</Style>
My question is. Is there a shortcut or better notation for doing this? I'm very
tempted to write a WPFCSS compiler to deal with this ;) Could I
write a MarkupExtension to clean it up. I would prefer any solutions to work
at design time as well if possible.
For example would it be possible to write an extension such as
<AncestorTrigger TargetType="ItemsControl" Path="Tag" Value="property">
<Setter Property="Grid.Row" Value="0"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Padding" Value="0,4,0,0"/>
</AncestorTrigger>
? This would be much easier than remembering how to write
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}, Path=Tag}" Value="property">
I wrote a custom behavior to solve this that also works at design time. The markup will
<DataTrigger
WPF:WhenParentTag.TargetType="{x:Type ItemsControl}" Value="property">
<Setter Property="Grid.Row" Value="0"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Padding" Value="0,4,0,0"/>
</DataTrigger>
which is a bit more sane. The code for the extension is
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Markup;
namespace My.WPF
{
public static class WhenParentTag
{
static WhenParentTag()
{}
public static readonly DependencyProperty
TargetTypeProperty =
DependencyProperty.RegisterAttached
( "TargetType"
, typeof(Type)
, typeof(WhenParentTag)
, new PropertyMetadata(null, TargetTypeChanged));
public static void
TargetTypeChanged
( DependencyObject dob
, DependencyPropertyChangedEventArgs e)
{
var trigger = dob as DataTrigger;
if(trigger==null){
return;
}
var type = e.NewValue as Type;
if (type == null)
return;
var binding = new Binding();
var rel = new RelativeSource(RelativeSourceMode.FindAncestor) { AncestorType = type };
binding.RelativeSource = rel;
binding.Path = new PropertyPath("Tag");
trigger.Binding = binding;
}
public static Type
GetTargetType
( DataTrigger dp)
{
return (Type)dp.GetValue(TargetTypeProperty);
}
public static void
SetTargetType
( DataTrigger dp,
Type value)
{
dp.SetValue(TargetTypeProperty, value);
}
}
}
Improvement suggestions are welcome.

Resources