I'm trying to create a simple Style
for the Header
of all the ToggleSwitche
s on a given Page
(WinUI 3 v1.2 desktop project). I'd really like to use x:Bind
for all of my bindings (not Binding
). Here's my Page.Resources
<Page.Resources>
<Style TargetType="ToggleSwitch" >
<Setter Property="FontSize" Value="{x:Bind app:App.ShellPage.RootShellFontSize, Mode=OneWay}" />
<Setter Property="Foreground" Value="{x:Bind app:App.ShellPage.UiColorContentAreaForeground, Mode=OneWay}" />
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate x:DataType="ToggleSwitch">
<TextBlock Text="{x:Bind Header}" Foreground="{x:Bind Foreground}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
and the ToggleSwitch is defined as
<ToggleSwitch Grid.Row="1" Grid.Column="1" Header="Resize Elements"
OffContent="Don't Resize" OnContent="Resize Everything"
IsOn="{x:Bind app:App.ShellPage.IsSettingsResizeElements, Mode=TwoWay}" />
I thought this would set the text in the Header
TextBlock
to whatever was set in the ToggleSwitch
Header
("Resize Elements" here) and bind the Foreground
of the Header
to UiColorContentAreaForeground
. Neither binding produces the expected results.
The first binding in the TextBlock
, Text="{x:Bind Header}"
, always throws an error as the binding engine tries to cast the string "Resize Elements"
to a ToggleSwitch
prior to looking at the Header
property. Using Text="{x:Bind}"
does the same thing as does Text="{x:Bind OnContent}"
or Text="{x:Bind OffContent}"
(!?). I can't think why the latter two happen as ToString()
returns the contents of Header
.
The second binding in TextBlock
binds to something but it has a different value than UiColorContentAreaForeground
(although it's always the same wrong value).
Any idea what's wrong with the bindings, please? How should I write the bindings using x:Bind?
As an aside, using Text="{Binding}"
works but I haven't found any form of binding that works for the Foreground
property.
The first binding in the TextBlock, Text="{x:Bind Header}", always throws an error as the binding engine tries to cast the string "Resize Elements" to a ToggleSwitch prior to looking at the Header property.
This is expected since you have set the Header
of the ToggleSwitch
to which your style is applied to this string value. The HeaderTemplate
is applied to the Header
.
For your style to work, you should set the Header
property of the ToggleSwitch
to another ToggleSwitch
which makes no sense.
What you could do is to set the Header
to a custom object like this:
public class ToggleSwitchHeader
{
public string Header { get; set; }
public Brush Foreground { get; set; }
}
XAML:
<ToggleSwitch Grid.Row="1" Grid.Column="1"
OffContent="Don't Resize" OnContent="Resize Everything">
<ToggleSwitch.Header>
<local:ToggleSwitchHeader Header="Resize Elements" Foreground="Red" />
</ToggleSwitch.Header>
</ToggleSwitch>
Then you can change the TargetType
of the DataTemplate
to this type and use compiled bindings (x:Bind
) in the template:
<Style TargetType="ToggleSwitch" >
<Setter Property="FontSize" Value="{x:Bind app:App.ShellPage.RootShellFontSize, Mode=OneWay}" />
<Setter Property="Foreground" Value="{x:Bind app:App.ShellPage.UiColorContentAreaForeground, Mode=OneWay}" />
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate x:DataType="local:ToggleSwitchHeader">
<TextBlock Text="{x:Bind Header}" Foreground="{x:Bind Foreground}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>