XAML 如何在WinUI 3中使用切换头模板的DataTemplate中的x:Bind

xcitsw88  于 2022-12-07  发布在  其他
关注(0)|答案(2)|浏览(195)

我试图为给定的Page(WinUI 3 v1.2桌面项目)上的所有ToggleSwitcheHeader创建一个简单的Style。我真的想为我的所有绑定使用x:Bind(而不是Binding)。下面是我的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>

ToggleSwitch定义为

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

我认为这会将HeaderTextBlock中的文本设置为ToggleSwitchHeader中的任何设置(此处为“调整元素大小”),并将HeaderForeground绑定到UiColorContentAreaForeground
第一个绑定在TextBlockText="{x:Bind Header}"、当绑定引擎在查看Header属性之前尝试将字符串"Resize Elements"转换为ToggleSwitch时,总是引发错误。使用Text="{x:Bind}"Text="{x:Bind OnContent}"Text="{x:Bind OffContent}"执行相同的操作(!?)。我想不出为什么后面两个会发生,因为ToString()返回Header的内容。
TextBlock中的第二个绑定与UiColorContentAreaForeground绑定,但它的值与UiColorContentAreaForeground不同(尽管它总是相同的错误值)。
你知道绑定有什么问题吗?我应该怎么用x:Bind写绑定呢?
顺便说一句,使用Text="{Binding}"是可行的,但我还没有找到任何适用于Foreground属性的绑定形式。

4ngedf3f

4ngedf3f1#

TextBlock中的第一个绑定Text="{x:Bind Header}"总是引发错误,因为绑定引擎在查看Header属性之前尝试将字符串“Resize Elements”转换为ToggleSwitch。
这是预料之中的,因为您已经将样式所应用到的ToggleSwitchHeader设置为此字符串值。HeaderTemplate将应用到Header
为了使您的样式正常工作,您应该将ToggleSwitchHeader属性设置为另一个没有意义的ToggleSwitch
您可以将Header设置为一个自定义对象,如下所示:

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>

然后,您可以将DataTemplateTargetType变更为这个型别,并在样板中使用已编译的系结(x:Bind):

<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>
wmvff8tz

wmvff8tz2#

谢谢@mm8!你让我在
HeaderTemplate应用于Header

虽然这应该是显而易见的,但我一直被DataTemplate的文档卡住了,它说x:Bind使用模板化对象作为它的根。我错误地解释了这一点,认为主对象上的所有DataTemplate(在本例中为ToggleSwitch)都将引用主对象。

为了向那些同样面临代码挑战的人澄清一下,正如@mm8所指出的,HeaderTemplate(我想FooterTemplate也是)实际上使用了赋给Header的对象(Footer),而ContentTemplate将使用整个ToggleSwitch
在本例中,我将String赋值给Header,因此绑定(使用x:Bind)的正确代码为

<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="x:String">
                    <TextBlock Text="{x:Bind}" Foreground="{x:Bind app:App.ShellPage.UiColorContentAreaForeground, Mode=OneWay}"/>
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Page.Resources>

TextBlock.Text直接绑定到在ToggleSwitch定义中分配给ToggleSwitch.Header的字符串对象

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

因为String没有Foreground属性,所以我必须使用@mm8建议的方法,或者将x:Bind直接用于StyleForegroundSetter中使用的相同Source(我在上面的解决方案中展示了它)。
再次感谢@mm8在我努力理解WinUI 3中XAML的细微差别时提供的帮助。

相关问题