I am using radio button control with customised radio button selection colors in .Net Maui.But when changing the selection , it doesn't fire CheckedChanged event.
Here is the code snippet,
View
<StackLayout
x:Name="SexRadioGroup"
Grid.Row="10"
Margin="24,12,0,0"
Orientation="Horizontal"
RadioButtonGroup.GroupName="SexRadioGroup"
Spacing="40">
<RadioButton
GroupName="SexRadioGroup"
IsChecked="True"
Value="Male">
<RadioButton.Content>
<StackLayout>
<Label
Margin="30,0,0,0"
Text="Male"
TextColor="{StaticResource FieldNameTextColor}"
VerticalOptions="Start" />
</StackLayout>
</RadioButton.Content>
</RadioButton>
<RadioButton
CheckedChanged="SexRadioButton_CheckedChanged"
GroupName="SexRadioGroup"
Value="Female">
<RadioButton.Content>
<StackLayout>
<Label
Margin="30,0,0,0"
Text="Female"
TextColor="{StaticResource FieldNameTextColor}"
VerticalOptions="Start" />
</StackLayout>
</RadioButton.Content>
</RadioButton>
</StackLayout>
Code behind file
private void SexRadioButton_CheckedChanged(object sender, CheckedChangedEventArgs e)
{
}
Style(RadioButton template)
<ControlTemplate x:Key="RadioButtonTemplate">
<Frame
Padding="0"
BackgroundColor="#F3F2F1"
BorderColor="#F3F2F1"
HasShadow="False"
HeightRequest="100"
HorizontalOptions="Start"
VerticalOptions="Start"
WidthRequest="100">
<Grid Margin="4" WidthRequest="100">
<Grid
HeightRequest="18"
HorizontalOptions="End"
VerticalOptions="Start"
WidthRequest="18">
<Ellipse
Fill="White"
HeightRequest="16"
HorizontalOptions="Center"
Stroke="Blue"
VerticalOptions="Center"
WidthRequest="16" />
<Ellipse
x:Name="check"
Fill="Blue"
HeightRequest="8"
HorizontalOptions="Center"
VerticalOptions="Center"
WidthRequest="8" />
</Grid>
<ContentPresenter />
</Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroupList>
<VisualStateGroup x:Name="CheckedStates">
<VisualState x:Name="Checked">
<VisualState.Setters>
<Setter Property="BorderColor" Value="#FF3300" />
<Setter TargetName="check" Property="Opacity" Value="1" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Unchecked">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="#F3F2F1" />
<Setter Property="BorderColor" Value="#F3F2F1" />
<Setter TargetName="check" Property="Opacity" Value="0" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</VisualStateManager.VisualStateGroups>
</Frame>
</ControlTemplate>
<Style TargetType="RadioButton">
<Setter Property="ControlTemplate" Value="{StaticResource RadioButtonTemplate}" />
</Style>
Is there any way to use renderer to change the selection and unselection color of the radio button by renderers?
The cause is the clicked event has been dealt with by the Frame, not the radio button. So you can add the TapGestureRecognizer to the Frame. I use the control template in the App.xaml. Such as:
<ControlTemplate x:Key="RadioButtonTemplate">
<Frame
Padding="0"
BackgroundColor="#F3F2F1"
BorderColor="#F3F2F1"
HasShadow="False"
HeightRequest="100"
HorizontalOptions="Start"
VerticalOptions="Start"
WidthRequest="100">
<Frame.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
</Frame.GestureRecognizers>
And in the App.cs:
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
Frame frame = sender as Frame;
RadioButton button = (RadioButton)frame.Parent;
button.IsChecked = true;
}
And then, the radio button checked changed event will be hit when you click it. (Note: On the windows platform, it can work without the TapGestureRecognizer.)
Related
I am running into some issues with styling a radio button in .Net MAUI. Initially, I noticed the the radio button look-and-feel is not consistent across Windows and Android, as can be seen in the image below:
Not only are they different, but the available options for styling the button are limited. The only options for defining colors are "BorderColor", "BackgroundColor", and "TextColor". Both "BorderColor" and "BackgroundColor" have absolutely no effect on the color of the radio button itself. I'd like to change the color of the actual radio button.
So I decided to create a control template to help me out. Here is my control template:
<ControlTemplate x:Key="RadioButtonTemplate">
<Border Stroke="Transparent" BackgroundColor="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroupList>
<VisualStateGroup x:Name="CheckedStates">
<VisualState x:Name="Checked">
<VisualState.Setters>
<Setter TargetName="check" Property="Opacity" Value="1" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Unchecked">
<VisualState.Setters>
<Setter TargetName="check" Property="Opacity" Value="0" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</VisualStateManager.VisualStateGroups>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid WidthRequest="20" HeightRequest="20" Grid.Column="0" VerticalOptions="Center" HorizontalOptions="Center">
<Ellipse x:Name="border_circle" StrokeThickness="2" Stroke="DarkBlue" Fill="White" WidthRequest="18" HeightRequest="18" HorizontalOptions="Center" VerticalOptions="Center" />
<Ellipse x:Name="check" Fill="DarkBlue" WidthRequest="10" HeightRequest="10" HorizontalOptions="Center" VerticalOptions="Center" />
</Grid>
<ContentPresenter Margin="10,0,0,0" Grid.Column="1" HorizontalOptions="Start" VerticalOptions="Center" />
</Grid>
</Border>
</ControlTemplate>
<Style TargetType="RadioButton" x:Key="RadioButtonStyle">
<Setter Property="ControlTemplate" Value="{StaticResource RadioButtonTemplate}" />
</Style>
This worked reasonably well, so now I get the following look-and-feel on both Android and Windows:
Now I have one last problem. When I was using the default radio buttons (without my control template), they would reliably turn a "light gray" color whenever I set IsEnabled to false. I'd like to make it so that I can disable my radio button and have it turn a light gray color (to indicate that it is disabled) while still using my control template so I have a unified look-and-feel.
So I attempted to add a Disabled visual state to my control template, but it doesn't seem to be working. Here is my new control template with a Disabled state:
<ControlTemplate x:Key="RadioButtonTemplate">
<Border Stroke="Transparent" BackgroundColor="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroupList>
<VisualStateGroup x:Name="CheckedStates">
<VisualState x:Name="Checked">
<VisualState.Setters>
<Setter TargetName="check" Property="Opacity" Value="1" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Unchecked">
<VisualState.Setters>
<Setter TargetName="check" Property="Opacity" Value="0" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter TargetName="border_circle" Property="Stroke" Value="LightGray" />
<Setter TargetName="check" Property="Fill" Value="LightGray" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</VisualStateManager.VisualStateGroups>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid WidthRequest="20" HeightRequest="20" Grid.Column="0" VerticalOptions="Center" HorizontalOptions="Center">
<Ellipse x:Name="border_circle" StrokeThickness="2" Stroke="DarkBlue" Fill="White" WidthRequest="18" HeightRequest="18" HorizontalOptions="Center" VerticalOptions="Center" />
<Ellipse x:Name="check" Fill="DarkBlue" WidthRequest="10" HeightRequest="10" HorizontalOptions="Center" VerticalOptions="Center" />
</Grid>
<ContentPresenter Margin="10,0,0,0" Grid.Column="1" HorizontalOptions="Start" VerticalOptions="Center" />
</Grid>
</Border>
</ControlTemplate>
<Style TargetType="RadioButton" x:Key="RadioButtonStyle">
<Setter Property="ControlTemplate" Value="{StaticResource RadioButtonTemplate}" />
</Style>
Unfortunately, it's not working. Not only does the color not change when the radio button is disabled, but also my 2nd setter (setting the "Fill" property of the "check" object) causes a compile-time error as well ("Cannot resolve property Fill on type Border").
Any suggestions?
I was able to figure out a way to do what I needed to do. Rather than use the "Disabled" visual state in the visual state group, I was able to use style triggers. So now my control template and its corresponding style look like this:
<ControlTemplate x:Key="RadioButtonTemplate">
<Border Stroke="Transparent" BackgroundColor="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroupList>
<VisualStateGroup x:Name="CheckedStates">
<VisualState x:Name="Checked">
<VisualState.Setters>
<Setter TargetName="check" Property="Opacity" Value="1" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Unchecked">
<VisualState.Setters>
<Setter TargetName="check" Property="Opacity" Value="0" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</VisualStateManager.VisualStateGroups>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid WidthRequest="20" HeightRequest="20" Grid.Column="0" VerticalOptions="Center" HorizontalOptions="Center">
<Ellipse x:Name="border_circle" StrokeThickness="2" Stroke="{TemplateBinding BorderColor}" Fill="White" WidthRequest="18" HeightRequest="18" HorizontalOptions="Center" VerticalOptions="Center" />
<Ellipse x:Name="check" Fill="{TemplateBinding BorderColor}" WidthRequest="10" HeightRequest="10" HorizontalOptions="Center" VerticalOptions="Center" />
</Grid>
<ContentPresenter Margin="10,0,0,0" Grid.Column="1" HorizontalOptions="Start" VerticalOptions="Center" />
</Grid>
</Border>
</ControlTemplate>
<Style TargetType="RadioButton" x:Key="RadioButtonStyle">
<Setter Property="ControlTemplate" Value="{StaticResource RadioButtonTemplate}" />
<Style.Triggers>
<Trigger TargetType="RadioButton" Property="IsEnabled" Value="False">
<Setter Property="BorderColor" Value="LightGray" />
</Trigger>
<Trigger TargetType="RadioButton" Property="IsEnabled" Value="True">
<Setter Property="BorderColor" Value="DarkBlue" />
</Trigger>
</Style.Triggers>
</Style>
I defined two ContentPage level styles to be bound dynamically to an ImageButton. When the ImageButton click event is called, it is supposed to switch the ImageButton style, but this is not happening.
Below is the ContentPage content with the styles and the ImageButton definition:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="SampleMobile.SamplePage"
Title="">
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="defaultStyle" TargetType="ImageButton">
<Setter Property="BorderColor" Value="Grey"/>
<Setter Property="BorderWidth" Value="2" />
</Style>
<Style x:Key="selectedStyle" TargetType="ImageButton">
<Setter Property="BorderColor" Value="Blue"/>
<Setter Property="BorderWidth" Value="5" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<Grid RowDefinitions="50, 100, 5, 100, 5, 50, 100, 100, 100" ColumnDefinitions="*, *, *, *"
Padding="25, 35, 25, 35" ColumnSpacing="5" RadioButtonGroup.GroupName="mobileNetworks">
<Label Grid.Row="0" Grid.ColumnSpan="4"
Text="Select Network"
VerticalOptions="Center"
HorizontalOptions="Center" />
<ImageButton Source="first.png" Grid.Row="1" Grid.Column="0" HeightRequest="50" WidthRequest="50" CornerRadius="10" Clicked="SelectImage" Style="{DynamicResource imageButtonStyle}"/>
<ImageButton Source="second.png" Grid.Row="1" Grid.Column="1" BorderWidth="2" HeightRequest="50" WidthRequest="50" BorderColor="Grey" CornerRadius="10"/>
<ImageButton Source="third.png" Grid.Row="1" Grid.Column="2" BorderWidth="2" HeightRequest="50" WidthRequest="50" BorderColor="Grey" CornerRadius="10"/>
<ImageButton Source="fourth.png" Grid.Row="1" Grid.Column="3" BorderWidth="2" HeightRequest="50" WidthRequest="50" BorderColor="Grey" CornerRadius="10"/>
</Grid>
</ContentPage>
Below is the code behind file where the first style is set, and the second style is set inside the click event handler:
public partial class SamplePage : ContentPage
{
public SamplePage()
{
InitializeComponent();
Resources["imageButtonStyle"] = Resources["defaultStyle"];
}
private void SelectImage(object sender, EventArgs e)
{
Resources["imageButtonStyle"] = Resources["selectedStyle"];
}
}
I'm still trying to find what is wrong, and why it is not working as expected.
You can use this.
First give the ImageButton a name like this x:Name="Image1"
I added 2 Buttons to change it and go back.
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="defaultStyle" TargetType="ImageButton">
<Setter Property="BorderColor" Value="Gray"/>
<Setter Property="BorderWidth" Value="2" />
</Style>
<Style x:Key="selectedStyle" TargetType="ImageButton">
<Setter Property="BorderColor" Value="Blue"/>
<Setter Property="BorderWidth" Value="5" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout>
<Frame BackgroundColor="#2196F3" Padding="24" CornerRadius="0">
<Label Text="Welcome to Xamarin.Forms!" HorizontalTextAlignment="Center" TextColor="White" FontSize="36"/>
</Frame>
<ImageButton x:Name="Image1" Source="balzwart.png" Style="{DynamicResource defaultStyle}" />
<Button Text="Change" Clicked="Button_Clicked" />
<Button Text="Back" Clicked="Button_Clicked_1" />
</StackLayout>
and for the Button Click
private void Button_Clicked(object sender, EventArgs e)
{
Image1.Style = (Style)Resources["selectedStyle"];
}
private void Button_Clicked_1(object sender, EventArgs e)
{
Image1.Style = (Style)Resources["defaultStyle"];
}
Find it here https://github.com/borisoprit/DynamicSO
Instead of manipulating the styles at runtime, which is only a semi-good idea and should be done differently anyway, I recommend you do something like below instead using Visual States and only one Style for the ImageButton:
<?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="SelectedImageSample.MainPage">
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="ImageButtonStyle" TargetType="ImageButton">
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Selected">
<VisualState.Setters>
<Setter Property="BorderColor" Value="Blue" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<Grid RowDefinitions="50, 100, 5, 100, 5, 50, 100, 100, 100" ColumnDefinitions="*, *, *, *"
Padding="25, 35, 25, 35" ColumnSpacing="5" RadioButtonGroup.GroupName="mobileNetworks">
<Label Grid.Row="0" Grid.ColumnSpan="4"
Text="Select Network"
VerticalOptions="Center"
HorizontalOptions="Center" />
<ImageButton Source="first.png" Grid.Row="1" Grid.Column="0" BorderWidth="2" HeightRequest="50" WidthRequest="50" CornerRadius="10" Clicked="SelectImage" Style="{StaticResource ImageButtonStyle}"/>
<ImageButton Source="second.png" Grid.Row="1" Grid.Column="1" BorderWidth="2" HeightRequest="50" WidthRequest="50" CornerRadius="10" Clicked="SelectImage" Style="{StaticResource ImageButtonStyle}"/>
<ImageButton Source="third.png" Grid.Row="1" Grid.Column="2" BorderWidth="2" HeightRequest="50" WidthRequest="50" CornerRadius="10" Clicked="SelectImage" Style="{StaticResource ImageButtonStyle}"/>
<ImageButton Source="fourth.png" Grid.Row="1" Grid.Column="3" BorderWidth="2" HeightRequest="50" WidthRequest="50" CornerRadius="10" Clicked="SelectImage" Style="{StaticResource ImageButtonStyle}"/>
</Grid>
</ContentPage>
In your Code Behind, you then can use the event handler to set the Visual State as follows:
private void SelectImage(object sender, EventArgs e)
{
if (sender is ImageButton imageButton)
{
VisualStateManager.GoToState(imageButton, "Selected");
}
}
This is just the minimal demonstration of how it can be done without manipulating a style in the resources. If you want to unselect the ImageButton again, you'll need to implement some logic and an Unselected Visual State.
Update 1
It might be useful to store some kind of state on the button by adding an IsSelected property (e.g. via inheritance). Then the Visual State can be updated accordingly.
Update 2
If you don't want to extend ImageButton, you could also use an Attached Property to store the state for the button.
Below image you see the red circle indicators where it's only possible to click and radiobutton works, but I want to scoop them to the correct place(to the left so it's aligned with UI), which I don't know how. I tried TranslationY=-80 but it didn't work.
Styles.xaml:
<ControlTemplate x:Key="RadioButtonTemplate">
<Frame BorderColor="#F3F2F1" CornerRadius="2" BackgroundColor="#F3F2F1" HasShadow="False" HeightRequest="80" WidthRequest="80" HorizontalOptions="Start" VerticalOptions="Start" Padding="0">
<VisualStateManager.VisualStateGroups>
<VisualStateGroupList>
<VisualStateGroup x:Name="CheckedStates">
<VisualState x:Name="Checked">
<VisualState.Setters>
<Setter Property="BorderColor" Value="#FF3300" />
<Setter TargetName="check" Property="Opacity" Value="1" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Unchecked">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="#F3F2F1" />
<Setter Property="BorderColor" Value="#F3F2F1" />
<Setter TargetName="check" Property="Opacity" Value="0" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</VisualStateManager.VisualStateGroups>
<Grid Margin="4" WidthRequest="80">
<Grid WidthRequest="18" HeightRequest="18" HorizontalOptions="End" VerticalOptions="Start">
<Ellipse Stroke="Blue" Fill="White" WidthRequest="16" HeightRequest="16" HorizontalOptions="Center" VerticalOptions="Center" />
<Ellipse x:Name="check" Fill="Blue" WidthRequest="8" HeightRequest="8" HorizontalOptions="Center" VerticalOptions="Center" />
</Grid>
<ContentPresenter />
</Grid>
</Frame>
</ControlTemplate>
<Style TargetType="RadioButton">
<Setter Property="ControlTemplate" Value="{StaticResource RadioButtonTemplate}" />
</Style>
MyPage.xaml:
<StackLayout Spacing="3">
<Label Text="{Binding SelectedTheme, StringFormat='Theme: {0}'}" FontSize="20" />
<Grid ColumnDefinitions="*,*,*" RadioButtonGroup.GroupName="themes" RadioButtonGroup.SelectedValue="{Binding SelectedTheme, Mode=TwoWay}">
<RadioButton Value="{x:Static am:AppTheme.Unspecified}" CheckedChanged="RadioButton_CheckedChanged">
<RadioButton.Content>
<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
<Image Scale="0.75" Source="{FontImage FontFamily=FAS, Glyph={x:Static fontawesome:FontAwesomeIcons.Gear}, Color=#323130}" />
<Label FontSize="Small" Text="System" TextColor="#323130" />
</StackLayout>
</RadioButton.Content>
</RadioButton>
<RadioButton Value="{x:Static am:AppTheme.Light}" Grid.Column="1" CheckedChanged="RadioButton_CheckedChanged">
<RadioButton.Content>
<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
<Image Scale="0.75" Source="{FontImage FontFamily=FAS, Glyph={x:Static fontawesome:FontAwesomeIcons.Sun}, Color=#323130}" />
<Label FontSize="Small" Text="Light" TextColor="#323130" />
</StackLayout>
</RadioButton.Content>
</RadioButton>
<RadioButton Value="{x:Static am:AppTheme.Dark}" Grid.Column="2" CheckedChanged="RadioButton_CheckedChanged">
<RadioButton.Content>
<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
<Image Scale="0.75" Source="{FontImage FontFamily=FAS, Glyph={x:Static fontawesome:FontAwesomeIcons.Moon}, Color=#323130}" />
<Label FontSize="Small" Text="Dark" TextColor="#323130" />
</StackLayout>
</RadioButton.Content>
</RadioButton>
</Grid>
</StackLayout>
It's hard to say it is a potential issue or by design .
To solve the problem/as a workaround , you can add a TapGestureRecognizer on ContentPresenter to enable the RadioButton manually .
Sample code
//xaml
<ContentPresenter >
<ContentPresenter.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
</ContentPresenter.GestureRecognizers>
</ContentPresenter>
//code behind
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
ContentPresenter cp = sender as ContentPresenter;
var button = cp.Content.Parent as RadioButton;
button.IsChecked = true;
}
I have a ControlTemplate to modify the appearance of a radioButton in Xamarin.Forms.
I borrowed/updated it from https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/radiobutton#redefine-radiobutton-appearance
It looks great, and the appearance is perfect when the page is created.
I want the image in the radiobutton to change depending on a binding, which it does not do.
The binding property gets modified, OnPropertyChanged() gets called, but the binding is not getting triggered.
Here is the general appearance (with two of these RadioButtons side by side)
Again, the appearance and the Converter and everything work just fine, but only when the page is first drawn.
Here is the ControlTemplate
<ControlTemplate x:Key="RadioButtonTemplate">
<Frame
BackgroundColor="#30888888"
HasShadow="False"
HeightRequest="{TemplateBinding HeightRequest}"
WidthRequest="{TemplateBinding WidthRequest}"
HorizontalOptions="Start"
VerticalOptions="StartAndExpand"
Padding="0">
<VisualStateManager.VisualStateGroups>
<VisualStateGroupList>
<VisualStateGroup x:Name="CheckedStates">
<VisualState x:Name="Checked">
<VisualState.Setters>
<Setter Property="BorderColor" Value="Accent" />
<Setter TargetName="check"
Property="Opacity"
Value="1" />
<Setter TargetName="checkrim"
Property="Opacity"
Value="1" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Unchecked">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="{DynamicResource TransparentBackgroundColour}" />
<Setter Property="BorderColor" Value="Transparent" />
<Setter TargetName="check"
Property="Opacity"
Value="0" />
<Setter TargetName="checkrim"
Property="Opacity"
Value="0" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</VisualStateManager.VisualStateGroups>
<Grid Margin="4"
WidthRequest="100">
<ContentPresenter Margin="6" />
<Grid WidthRequest="20"
HeightRequest="20"
Padding="0"
HorizontalOptions="Start"
VerticalOptions="Start">
<Ellipse x:Name="unckecd"
Stroke="White"
StrokeThickness="2"
Fill="Transparent"
Margin="0"
WidthRequest="20" HeightRequest="20"
HorizontalOptions="Center" VerticalOptions="Center" />
<Ellipse x:Name="checkrim"
Stroke="Accent"
StrokeThickness="2"
Fill="Transparent"
Margin="0"
WidthRequest="20" HeightRequest="20"
HorizontalOptions="Center" VerticalOptions="Center" />
<Ellipse x:Name="check"
Fill="Accent"
Margin="1,1,0,0"
WidthRequest="10" HeightRequest="10"
HorizontalOptions="Center" VerticalOptions="Center" />
</Grid>
</Grid>
</Frame>
</ControlTemplate>
And the Style of my RadioButton
<Style x:Key="FancyRadioButton" TargetType="RadioButton">
<Setter Property="ControlTemplate"
Value="{DynamicResource RadioButtonTemplate}" />
</Style>
And my RadioButton
<RadioButton Style="{StaticResource FancyRadioButton}"
Value="{x:Static gdl90Types:UdpTransmitMode.UdpUnicast}"
WidthRequest="150"
HeightRequest="103">
<RadioButton.Content>
<StackLayout VerticalOptions="Start" Spacing="0" Margin="0, -3">
<Image Source="{Binding Source=ColourPresetSetting,
ConverterParameter=unicast,
Converter={StaticResource ResourceImageFromThemeConverter}}"
Margin="22,0"
Aspect="AspectFit"
/>
<Label Text="UDP UNICAST" TextColor="{DynamicResource MediumContrastTextColour}" />
</StackLayout>
</RadioButton.Content>
All I want is for the Image in the RadioButton to notice the property ColourPresetSetting changing, to update the image.
It does it when first drawn, but no longer after that.
Am I missing something obvious?
I am new to UWP development and working on XAML. Can someone tell me what is wrong with the following XAML where visual state is not working. when I resize the window, the values of rows and columns do not change. Also the background color of the stack panel does not change.
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Margin="40,0,0,0">
<GridView ItemsSource="{x:Bind Ticket}">
<GridView.ItemTemplate>
<DataTemplate x:DataType="data:Ticket">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="NarrowLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="600" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="StackPanel00.Background" Value="Blue" />
<Setter Target="StackPanel00.(Grid.Column)" Value="0" />
<Setter Target="StackPanel00.(Grid.Row)" Value="0" />
<Setter Target="StackPanel01.(Grid.Column)" Value="0" />
<Setter Target="StackPanel01.(Grid.Row)" Value="1" />
<Setter Target="StackPanel10.(Grid.Row)" Value="2" />
<Setter Target="StackPanel10.(Grid.Column)" Value="0" />
<Setter Target="StackPanel11.(Grid.Column)" Value="0" />
<Setter Target="StackPanel11.(Grid.Row)" Value="3" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="WideLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="1100" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="StackPanel00.(Grid.Column)" Value="0" />
<Setter Target="StackPanel00.(Grid.Row)" Value="0" />
<Setter Target="StackPanel01.(Grid.Column)" Value="1" />
<Setter Target="StackPanel01.(Grid.Row)" Value="0" />
<Setter Target="StackPanel10.(Grid.Row)" Value="1" />
<Setter Target="StackPanel10.(Grid.Column)" Value="0" />
<Setter Target="StackPanel11.(Grid.Column)" Value="1" />
<Setter Target="StackPanel11.(Grid.Row)" Value="1" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Name="StackPanel00" Grid.Row="0" Grid.Column="0" Margin="20">
<StackPanel Name="StackPanel000" Orientation="Horizontal">
<TextBlock Name="TicketLineLabel" Text="Ticket Line: " />
<TextBlock Name="TicketLineData" Text="{x:Bind Line}" Margin="10,0,0,0" />
</StackPanel>
<StackPanel Name="StackPanel001" Orientation="Horizontal" Margin="0,10,0,0" >
<TextBlock Name="TicketLocationLabel" Text="Ticket Location: " />
<TextBlock Name="TicketLocationData" Text="{x:Bind TicketLocation}" Margin="10,0,0,0" />
</StackPanel>
</StackPanel>
<StackPanel Name="StackPanel01" Grid.Row="0" Grid.Column="1" Margin="20">
<StackPanel Orientation="Horizontal" >
<TextBlock Name="StopDateFromLabel" Text="Stop Date From: " />
<TextBlock Name="StopDateFromData" Text="{x:Bind StopDateTime}" Margin="10,0,0,0" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,10,0,0">
<TextBlock Name="InvoiceDateLabel" Text="Invoice Date: " />
<TextBlock Name="InvoiceDateData" Text="{x:Bind InvoiceDate}" Margin="10,0,0,0" />
</StackPanel>
</StackPanel>
<StackPanel Name="StackPanel10" Grid.Row="1" Grid.Column="0" Margin="20">
<StackPanel Orientation="Horizontal">
<TextBlock Name="NetBarrelsLabel" Text="Net Barrels: " RelativePanel.AlignLeftWithPanel="True" />
<TextBlock Name="NetBarrelsData" Text="{x:Bind NetBarrels}" RelativePanel.RightOf="NetBarrelsLabel" Margin="10,0,0,0" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,10,0,0">
<TextBlock Name="WaterBarrelsLabel" Text="Water Barrels: " RelativePanel.AlignLeftWithPanel="True" />
<TextBlock Name="WaterBarrelsData" Text="{x:Bind NetBarrels}" RelativePanel.RightOf="WaterBarrelsLabel" Margin="10,0,0,0" />
</StackPanel>
</StackPanel>
<StackPanel Name="StackPanel11" Margin="20">
<StackPanel Orientation="Horizontal">
<TextBlock Name="TicketTypeLabel" Text="Ticket Type: " RelativePanel.AlignLeftWithPanel="True" />
<TextBlock Name="TicketTypeData" Text="{x:Bind TicketType}" RelativePanel.RightOf="TicketTypeLabel" Margin="10,0,0,0" />
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,10,0,0">
<TextBlock Name="OriginBillingTypeLabel" Text="Origin Billing Type: " RelativePanel.AlignLeftWithPanel="True" />
<TextBlock Name="OriginBillingTypeData" Text="{x:Bind OriginBillingType}" RelativePanel.RightOf="OriginBillingTypeLabel" Margin="10,0,0,0" />
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
To make the VisualStateManager work inside a DataTemplate, we will need to place it within a Control subclass such as a UserControl like the following:
<GridView ItemsSource="{x:Bind Ticket}">
<GridView.ItemTemplate>
<DataTemplate x:DataType="data:Ticket">
<UserControl>
<Grid>
<VisualStateManager.VisualStateGroups>
...
</VisualStateManager.VisualStateGroups>
...
</Grid>
</UserControl>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
Visual states are sometimes useful for scenarios where you want to change the state of some area of UI that's not immediately a Control subclass. You can't do this directly because the control parameter of the GoToState method requires a Control subclass, which refers to the object that the VisualStateManager acts upon.
We recommend you define a custom UserControl to either be the Window.Content root or be a container for other content you want to apply states to (such as a Panel). Then you can call GoToState on your UserControl and apply states regardless of whether the rest of the content is a Control.
For more info, please see Visual states for elements that aren't controls under Remarks of VisualStateManager Class.