【问题标题】:How do I bind datatemplate in a resource dictionary如何在资源字典中绑定数据模板
【发布时间】:2015-04-21 15:43:27
【问题描述】:

我正在尝试将我的元素绑定到字典中定义的数据模板中。 让我们变得简单。

我有一个简单的课程

public class A { public string Data {get;set} }

我有一个包含 ListBox 的简单视图,其中 ItemSources 是 A 类的列表:

<ListBox ItemsSource="{Binding AList}">

关键是,当我直接在视图中定义 Itemplate 时,绑定有效:

<ListBox.ItemTemplate>
   <DataTemplate >
      <TextBlock Text="{Binding Data}" />
      <Rectangle Fill="Red" Height="10" Width="10"/>
   </DataTemplate>
 </ListBox.ItemTemplate>

这很好用。

但是当我在资源字典中定义这个 ItemTemplate 时,绑定不起作用?

我该怎么做?

PS:这是一个简单的例子来解释我的问题,不要告诉我重写 toString 函数以使其工作或使用类模板,我的实际情况比这要复杂得多。

感谢您的帮助

【问题讨论】:

    标签: c# wpf styles


    【解决方案1】:

    创建一个新的 Dictionary1.xaml

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <DataTemplate x:Key="dataTemplate">
            <StackPanel>
                <TextBlock Text="{Binding Data}" />
                <Rectangle Fill="Red" Height="10" Width="10"/>
            </StackPanel>
        </DataTemplate>
    </ResourceDictionary>
    

    在 MainWindow.xaml 中引用它

    <Window.Resources>
        <ResourceDictionary Source="Dictionary1.xaml" />
    </Window.Resources>
    <ListBox Name="lst" ItemTemplate="{StaticResource dataTemplate}"></ListBox>
    

    MainWindow.cs:

    public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
            {
                var observable = new ObservableCollection<Test>();
                observable.Add(new Test("A"));
                observable.Add(new Test("B"));
                observable.Add(new Test("C"));
                this.lst.ItemsSource = observable;
            }
        }
    
        public class Test
        {
            public Test(string dateTime)
            {
                this.Data = dateTime;
            }
    
            public string Data { get; set; }
        }
    

    【讨论】:

    • 是的,我是通过在应用程序资源中加载字典来实现的(因为它包含多个窗口的数据)并使用动态资源,因为它在运行时根据皮肤加载。而且它不起作用:(
    • 您好,我将 ResourceDictionary 从 Dictionary1.xaml 移至 App.xaml (...) 它在这里工作。
    • 是的,你是对的。我的错误是因为我在 App() 构造函数中将字典加载到 Application.Current.Resources.MergedDictionaries 中。我将它移到 OnStartup 事件中,然后它就可以工作了。谢谢
    【解决方案2】:

    你给你的DataTemplate一个Key,这样你就可以使用明确定义你的模板并重用你的模板。您还需要确保ItemsControl 是加载字典的控件的子控件。

    <DataTemplate x:Key="ADataTemplate">
       <TextBlock Text="{Binding Data}" />
       <Rectangle Fill="Red" Height="10" Width="10"/>
    </DataTemplate>
    
    <ListBox ItemsSource="{Binding YourItems}"
             ItemTemplate="{StaticResource ADataTemplate}" />
    

    注意:您可以在 ListBox 上使用隐式样式,但是这会将相同的样式应用于您的所有 ListBoxes。

    【讨论】:

    • 这就是我正在做的,但是在资源字典中定义 DataTemplate 会使绑定不起作用...
    【解决方案3】:

    在当前窗口/用户控件等的资源部分声明你的数据模板如下,然后通过静态资源声明引用:

    <Window.Resources> For example...
    
       <DataTemplate x:Key="MyTemplate">
        <TextBlock Text="{Binding Data}" />
        <Rectangle Fill="Red" Height="10" Width="10"/>
       </DataTemplate>
    </Window.Resources>
    
    <ListBox ItemTemplate="{StaticResource MyTemplate}" />
    

    【讨论】:

    • 我不能,我必须在资源字典中这样做,因为我的资源字典是在运行时根据所选皮肤加载的
    • 数据模板声明将是相同的。 只是 Window 级别的资源字典。在您选择的资源字典中声明数据模板。
    • 如果主题在运行时发生更改,您可能想尝试 DynamicResource 而不是 StaticResource。这将确保始终对其进行评估,但可能会导致轻微的性能损失。
    猜你喜欢
    • 2022-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-26
    • 2019-12-14
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    相关资源
    最近更新 更多