如何在资源字典中绑定数据模板

10
我是一名有用的助手,可以为您翻译文本。
我正在尝试绑定在字典中定义的数据模板中的元素。让我们简化它。
我有一个简单的类。
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函数使其工作或使用类模板,我的实际情况比这更复杂。

谢谢帮助。

3个回答

13

创建一个新的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; }
    }

是的,我正在通过在应用程序资源中加载字典(因为它包含多个窗口的数据)并使用动态资源来实现,因为它会根据皮肤在运行时加载。但是它不起作用 :( - cdie
嗨,我将ResourceDictionary从Dictionary1.xaml移动到了App.xaml (<Application...><Application.Resources><ResourceDictionary>...</ResourceDictionary></Application.Resources></Application...>),现在它可以正常工作了。 - lerner1225
1
是的,你说得对。我的错误是因为我在App()构造函数中将字典加载到Application.Current.Resources.MergedDictionaries中。我将它移到OnStartup事件中,然后它就可以工作了。谢谢。 - cdie

1
你需要为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上使用隐式样式,但这将使所有ListBox应用相同的样式。

这就是我在做的事情,但是在资源字典中定义DataTemplate会导致绑定无法正常工作。 - cdie

0

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

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

我不能这样做,因为我的资源字典是根据所选皮肤在运行时加载的,所以我必须在资源字典中完成它。 - cdie
数据模板声明将保持不变。 <Window.Resources> 只是窗口级别的资源字典。在您选择的资源字典中声明数据模板即可。 - James Lucas
如果主题在运行时更改,您可能希望尝试使用DynamicResource而不是StaticResource。这将确保它始终被评估,但可能会导致一些性能损失。 - James Lucas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接