重用元素和DataContext
本文关键字:DataContext 元素 | 更新日期: 2023-09-27 18:29:36
我有两个类,它们引用第三个:
class Data1
{
public Named Xxx { get; set; }
public SomeClass1 Foo { get; set; }
...
}
class Data2
{
public Named Yyy { get; set; }
public SomeClass2 Bar { get; set; }
...
}
class Named
{
public string Name { get; set; }
...
}
现在,我想显示Data1
&Data2
:
<TreeView DataContext={Binding Path=Data1}>
<TreeView.Items>
<TreeViewItem>
<TreeViewItem.Header>
<StackPanel Orientation="Horizontal">
<ContentControl xml:space="preserve">Name: </ContentControl>
<ContentControl Content="{Binding Path=Xxx.Name}" />
</StackPanel>
</TreeViewItem.Header>
</TreeViewItem>
<TreeViewItem><!-- somehow display Foo --></TreeViewItem>
<!-- More TreeViewItems, specific to Data1 -->
</TreeView.Items>
</TreeView>
<TreeView DataContext={Binding Path=Data2}>
<TreeView.Items>
<TreeViewItem>
<TreeViewItem.Header>
<StackPanel Orientation="Horizontal">
<ContentControl xml:space="preserve">Name: </ContentControl>
<ContentControl Content="{Binding Path=Yyy.Name}" />
</StackPanel>
</TreeViewItem.Header>
</TreeViewItem>
<TreeViewItem><!-- somehow display Bar --></TreeViewItem>
<!-- More TreeViewItems, specific to Data2 -->
</TreeView.Items>
</TreeView>
因此,除了显示Named
类的TreeViewItem
之外,标记是不同的。我想为这个TreeViewItem
重用标记。制作UserControl
太简单了,但它仍然比示例中显示的要复杂一些。所以,我真的很想做这样的事情:
<ResourceDictionary>
<TreeViewItem x:Key="Named">
<TreeViewItem.Header>
<StackPanel Orientation="Horizontal">
<ContentControl xml:space="preserve">Name: </ContentControl>
<ContentControl Content="{Binding Path=Name}" />
</StackPanel>
</TreeViewItem.Header>
</TreeViewItem>
</ResourceDictionary>
然后像这样使用:
<TreeView DataContext={Binding Path=Data1}>
<TreeView.Items>
<StaticResource ResourceKey="Named" />
</TreeView.Items>
</TreeView>
如您所见,Data1
对Named
的属性名称为Xxx
,而Data2
对Named
的属性名称则为Yyy
。所以,我必须以某种方式将其传递给我的资源。但是怎么做呢?
例如,如何将此StaticResource
子树的DataContext
设置为Data1
的Xxx
?
这样的东西不起作用:
<StaticResource ResourceKey="Named" DataContext={Binding Path=Xxx} />
很抱歉问题太长。
编辑:
我只想要一个XAML,能够显示一个Named
实例。因此,我希望能够指定在哪里获取该片段外部的实例(来自Xxx
或Yyy
),这样我就可以重用它。
Edit2:这是ControlTemplate
的解决方案,但效果不佳:TreeViewItem
变得不可选择。怎么了?
<ControlTemplate x:Key="Named" TargetType="TreeViewItem">
<TreeViewItem>
<TreeViewItem.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Name: " />
<TextBlock Text="{Binding Path=Name}" />
</StackPanel>
</TreeViewItem.Header>
</TreeViewItem>
</ControlTemplate>
<!-- now use the template: -->
<TreeView>
<TreeView.Items>
<TreeViewItem Template="{StaticResource Named}"
DataContext="{Binding Path=Xxx}" />
...
您应该了解整个模板主题。与其手动创建TreeViewItem
的实例,不如将项目列表绑定到TreeView.ItemsSource
属性,然后指定一个TreeView.ItemTemplate
,它是可重用的静态资源。如果您有混合数据类型,那么您可以使用TreeView.ItemTemplateSelector
动态选择您想要的 DataTemplate
请参阅http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.itemtemplateselector.aspx有关更多信息,
根据您的评论,torvin,您应该使用DataTemplate。ItemsControl不仅支持模板化,ContentControl也具有此功能。存在ContentTemplate属性。ContentControl还通过使用DataTemplate.DataType属性自动挂接模板。
因此,您可以创建表示命名对象的DataTemplate:
<...Resources>
<DataTemplate DataType="{x:Type local:Named}">
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</...Resources>
然后您应该将Named对象设置为Content:
<TreeViewItem.Header>
<StackPanel Orientation="Horizontal">
<ContentControl xml:space="preserve">Name: </ContentControl>
<ContentControl Content="{Binding Path=Xxx}" />
</StackPanel>
</TreeViewItem.Header>
仅此而已!我希望这次能正确理解你:)
如果您想要StaticResource
中的Binding
s,请使用Hillberg的可冻结技巧
好吧,我今天睡了个午觉,当我醒来时,我突然意识到答案是什么!这是:
<!-- In resources: -->
<Style TargetType="TreeViewItem" x:Key="Named">
<Setter Property="Header" Value="{Binding Name}" />
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Name: " />
<TextBlock Text="{Binding}" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- now use the template: -->
<TreeView>
<TreeView.Items>
<TreeViewItem Style="{StaticResource Named}"
DataContext="{Binding Path=Xxx}" />
...