I have the following code:
MainPage.xml
<ContentPage x:Class="Test1.MainPage"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
Title="MainPage">
<ContentPage.Resources>
<DataTemplate x:Key="DefaultItemTemplate">
<Border Stroke="Transparent" BackgroundColor="WhiteSmoke" StrokeShape="RoundRectangle 4"
MinimumWidthRequest="36" MinimumHeightRequest="36">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal" />
<VisualState Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="{StaticResource Primary}" />
<Setter TargetName="Index" Property="Label.TextColor" Value="White" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Label x:Name="Index" Text="X" TextColor="Black" HorizontalOptions="Center" VerticalOptions="Center" />
</Border>
</DataTemplate>
</ContentPage.Resources>
<StackLayout Padding="16" Spacing="12">
<StackLayout Orientation="Horizontal">
<Label Text="1"/>
<CheckBox x:Name="Check1" CheckedChanged="Check1_CheckedChanged"/>
<ContentView x:Name="ContentView1"/>
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="2"/>
<CheckBox x:Name="Check2" CheckedChanged="Check2_CheckedChanged"/>
<ContentView x:Name="ContentView2"/>
</StackLayout>
</StackLayout>
</ContentPage>
MainPage.xaml.cs
using Microsoft.Maui.Controls.Shapes;
namespace Test1;
public partial class MainPage : ContentPage {
View view1;
View view2;
public MainPage() {
InitializeComponent();
//Taked from xaml resource
view1 = (View)((DataTemplate)Resources["DefaultItemTemplate"]).CreateContent();
ContentView1.Content = view1;
//Created by code
view2 = (View)DefaultItemTemplate.CreateContent();
ContentView2.Content = view2;
}
private void Check1_CheckedChanged(object sender, CheckedChangedEventArgs e) {
try {
VisualStateManager.GoToState(view1, e.Value ? "Selected" : "Normal");
var asd = view1.FindByName("Index");
System.Diagnostics.Debug.WriteLine(asd ?? "null"); // works ok, it gets the label
} catch (Exception ex) {
System.Diagnostics.Debug.WriteLine($"Error: {ex}");
}
}
private void Check2_CheckedChanged(object sender, CheckedChangedEventArgs e) {
try {
VisualStateManager.GoToState(view2, e.Value ? "Selected" : "Normal");
var asd = view2.FindByName("Index");
System.Diagnostics.Debug.WriteLine(asd ?? "null"); // returns null, label not found??
} catch (Exception ex) {
System.Diagnostics.Debug.WriteLine($"Error: {ex}");
}
}
private static DataTemplate DefaultItemTemplate => new DataTemplate( () => {
var view = new Border() {
Stroke = Colors.Transparent,
BackgroundColor = Colors.WhiteSmoke,
StrokeShape = new RoundRectangle { CornerRadius = 4 },
MinimumWidthRequest = 36,
MinimumHeightRequest = 36,
};
var label = new Label() {
StyleId = "Index", // it doenst work
Text = "X",
TextColor = Colors.Black,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
};
view.Content = label;
var commonStateGoup = new VisualStateGroup { Name = "CommonStates" };
var stateNormal = new VisualState { Name = "Normal" };
var stateSelected = new VisualState { Name = "Selected" };
stateSelected.Setters.Add(new Setter {
Property = BackgroundColorProperty,
Value = Application.Current!.Resources.TryGetValue("Primary",out var primaryColor) ? (Color)primaryColor : Colors.BlueViolet,
});
// Commenting this works, but label is not affected. Else
/*
stateSelected.Setters.Add(new Setter {
TargetName = "Index", // doesnt work
Property = Label.TextColorProperty,
Value = Colors.White,
});
*/
commonStateGoup.States.Add(stateNormal);
commonStateGoup.States.Add(stateSelected);
VisualStateManager.GetVisualStateGroups(view).Add(commonStateGoup);
return view;
});
}
what im trying to achieve is to create the DefaultItemTemplate
from the xaml resource but by code, and currently i cant make the VisualStateManager target the Label. It works as expected if i take the template from the xaml page resource, but not from de code behind.
How can i make it work?
Thanks to the link posted in comments by Liqun Shen-MSFT
, i could get it work. Here is the DataTemplate
code:
private static DataTemplate DefaultItemTemplate => new( () => {
var view = new Border() {
Stroke = Colors.Transparent,
StrokeThickness = 4d,
BackgroundColor = Colors.WhiteSmoke,
StrokeShape = new RoundRectangle { CornerRadius = 4 },
MinimumWidthRequest = 36,
MinimumHeightRequest = 36,
};
var label = new Label() {
Text = "-",
TextColor = Colors.Black,
FontSize = 14,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
};
view.Content = label;
// using Microsoft.Maui.Controls.Internals;
// this make the magic, you need to set the namescope and register the name this way
INameScope nameScope = new NameScope();
NameScope.SetNameScope(view, nameScope);
//nameScope.RegisterName("Root", view);
nameScope.RegisterName("Index", label);
var commonStateGoup = new VisualStateGroup { Name = "CommonStates" };
var stateNormal = new VisualState { Name = "Normal" };
var stateSelected = new VisualState { Name = "Selected" };
stateNormal.Setters.Add(new());
stateSelected.Setters.Add(new Setter {
//TargetName = "Root",
Property = BackgroundColorProperty,
Value = Application.Current!.Resources.TryGetValue("Primary",out var primaryColor) ? (Color)primaryColor : Colors.BlueViolet,
});
stateSelected.Setters.Add(new Setter {
TargetName = "Index",
Property = Label.TextColorProperty,
Value = Colors.White,
});
commonStateGoup.States.Add(stateNormal);
commonStateGoup.States.Add(stateSelected);
VisualStateManager.GetVisualStateGroups(view).Add(commonStateGoup);
return view;
});