UWP:如何在 ResourceDictionary 中使用 x:bind?
UWP : How to use x:bind in ResourceDictionary?
我想像在 WPF 中一样在 UWP 中使用 ResourceDictionary
在 WPF 中,我在 ResourceDictionary 文件中执行此操作(*Style.xaml)
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
xmlns:models="using:NWP.Models">
<Style x:key="MenuContent" TargetType="ContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<controls:DockPanel>
<ItemsControl ItemsSource="{x:Bind How-Can-I-Bind-Collection-Here?}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="models:MenuItemModel">
<RadioButton GroupName="MenuItems" IsChecked="{x:Binding IsChecked, Mode=TwoWay}" MinHeight="0" MinWidth="0" Command="{Binding Command}" CommandParameter="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentTransitions="{TemplateBinding ContentTransitions}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</controls:DockPanel>
</ControlTemplate>
</Setter.Value>
</Style>
</ResourceDictionary>
然后我可以在我的页面中使用这种样式:
<ContentControl Style="{StaticResource MenuContent}">
<StackPanel Orientation="Vertical">
<TextBox/>
<PasswordBox/>
<Button Content="Login"/>
</StackPanel>
</ContentControl>
但是现在,我正在努力研究如何使用 x:bind:
在 ResourceDictionary 的 ItemsControl 中为 ItemsSource 提供源
<ItemsControl ItemsSource="{x:Bind How-Can-I-Bind-Collection-Here?}">
我的问题是,如何解决这个问题?
添加@Bite的建议,我需要为您解释更多信息。在该文件中,它说:
if you use {x:Bind} in a resource dictionary then the resource dictionary needs to have a code-behind class.
- 从文档页面上看,听起来它可以工作,使用支持 class 作为绑定源,就像任何其他 x:Bind,但编译器明确拒绝 any x:Bind 在风格中。它根本不受支持。因此,您不能在 Style 中使用 x:Bind,即使是在 Style 中定义的 DataTemplate。
- 为了使用 x:Bind 中定义的 DataTemplate
ResourceDictionary,你需要为它创建一个class背后的代码。
由于第 1 点,此模板仍必须在任何样式 之外,但您需要支持 class 才能使 x:Bind 从
ResourceDictionary.
- 要使用基于 ResourceDictionary 的方法使项源绑定起作用,您需要使用旧版 {Binding} 而不是 {x:Bind}。
- 由于我们必须使用旧版 {Binding} 才能使其正常工作,因此必须通过设置 and/or 调整 ContentControl 的 DataContext 来自定义项目源。
那么,我做了一个简单的代码示例供大家参考:
<ResourceDictionary
x:Class="AppStyle.MenuDictionary"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:AppStyle"
xmlns:System="using:System">
<Style x:Key="MenuContent" TargetType="ContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ItemsControl ItemsSource="{Binding MenuItems}" ItemTemplate="{StaticResource MenuItemDataTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<ContentPresenter Grid.Row="1" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentTransitions="{TemplateBinding ContentTransitions}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="MenuItemDataTemplate" x:DataType="System:String">
<RadioButton GroupName="MenuItems" MinHeight="0" MinWidth="0" Content="{x:Bind}" />
</DataTemplate>
public sealed partial class MenuDictionary : ResourceDictionary
{
public MenuDictionary()
{
this.InitializeComponent();
}
}
<Page
x:Class="AppStyle.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:AppStyle"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<local:MenuDictionary/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ContentControl Style="{StaticResource MenuContent}">
<StackPanel>
<TextBlock>Test</TextBlock>
<TextBox />
</StackPanel>
</ContentControl>
</Grid>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.DataContext = this;
}
public IEnumerable<string> MenuItems => new string[] { "Page Item 1", "Page Item 2", };
}
我想像在 WPF 中一样在 UWP 中使用 ResourceDictionary 在 WPF 中,我在 ResourceDictionary 文件中执行此操作(*Style.xaml)
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
xmlns:models="using:NWP.Models">
<Style x:key="MenuContent" TargetType="ContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<controls:DockPanel>
<ItemsControl ItemsSource="{x:Bind How-Can-I-Bind-Collection-Here?}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="models:MenuItemModel">
<RadioButton GroupName="MenuItems" IsChecked="{x:Binding IsChecked, Mode=TwoWay}" MinHeight="0" MinWidth="0" Command="{Binding Command}" CommandParameter="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentTransitions="{TemplateBinding ContentTransitions}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</controls:DockPanel>
</ControlTemplate>
</Setter.Value>
</Style>
</ResourceDictionary>
然后我可以在我的页面中使用这种样式:
<ContentControl Style="{StaticResource MenuContent}">
<StackPanel Orientation="Vertical">
<TextBox/>
<PasswordBox/>
<Button Content="Login"/>
</StackPanel>
</ContentControl>
但是现在,我正在努力研究如何使用 x:bind:
在 ResourceDictionary 的 ItemsControl 中为 ItemsSource 提供源<ItemsControl ItemsSource="{x:Bind How-Can-I-Bind-Collection-Here?}">
我的问题是,如何解决这个问题?
添加@Bite的建议,我需要为您解释更多信息。在该文件中,它说:
if you use {x:Bind} in a resource dictionary then the resource dictionary needs to have a code-behind class.
- 从文档页面上看,听起来它可以工作,使用支持 class 作为绑定源,就像任何其他 x:Bind,但编译器明确拒绝 any x:Bind 在风格中。它根本不受支持。因此,您不能在 Style 中使用 x:Bind,即使是在 Style 中定义的 DataTemplate。
- 为了使用 x:Bind 中定义的 DataTemplate ResourceDictionary,你需要为它创建一个class背后的代码。 由于第 1 点,此模板仍必须在任何样式 之外,但您需要支持 class 才能使 x:Bind 从 ResourceDictionary.
- 要使用基于 ResourceDictionary 的方法使项源绑定起作用,您需要使用旧版 {Binding} 而不是 {x:Bind}。
- 由于我们必须使用旧版 {Binding} 才能使其正常工作,因此必须通过设置 and/or 调整 ContentControl 的 DataContext 来自定义项目源。
那么,我做了一个简单的代码示例供大家参考:
<ResourceDictionary
x:Class="AppStyle.MenuDictionary"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:AppStyle"
xmlns:System="using:System">
<Style x:Key="MenuContent" TargetType="ContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ItemsControl ItemsSource="{Binding MenuItems}" ItemTemplate="{StaticResource MenuItemDataTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<ContentPresenter Grid.Row="1" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentTransitions="{TemplateBinding ContentTransitions}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="MenuItemDataTemplate" x:DataType="System:String">
<RadioButton GroupName="MenuItems" MinHeight="0" MinWidth="0" Content="{x:Bind}" />
</DataTemplate>
public sealed partial class MenuDictionary : ResourceDictionary
{
public MenuDictionary()
{
this.InitializeComponent();
}
}
<Page
x:Class="AppStyle.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:AppStyle"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<local:MenuDictionary/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ContentControl Style="{StaticResource MenuContent}">
<StackPanel>
<TextBlock>Test</TextBlock>
<TextBox />
</StackPanel>
</ContentControl>
</Grid>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.DataContext = this;
}
public IEnumerable<string> MenuItems => new string[] { "Page Item 1", "Page Item 2", };
}