重用元素和DataContext

时间:2012-04-01 10:48:32

标签: c# .net wpf xaml

我有两个类,引用第三个:

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>

因此,除了显示TreeViewItem类的Named之外,标记是不同的。我想为此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的{​​{1}}属性名称为Named,而Xxx的{​​{1}}属性名称为{{1} }}。所以,我必须以某种方式将其传递给我的资源。但是如何?

E.g。如何为Data2将此Named子树的Yyy设置为DataContext

这样的事情不起作用:

StaticResource

很抱歉这个问题很长。

修改

我想要的只是一块XAML,能够显示Xxx个实例。所以,我希望能够指定从这件作品中获取实例的位置(来自Data1 <StaticResource ResourceKey="Named" DataContext={Binding Path=Xxx} /> ,因此我可以重复使用它。

Edit2 :这是Named的解决方案,但效果不佳:Xxx无法选择。怎么了?

Yyy

4 个答案:

答案 0 :(得分:1)

你应该看看整个模板主题。 您应该将项目列表绑定到TreeViewItem属性,而不是手动创建TreeView.ItemsSource实例,然后指定TreeView.ItemTemplate这是您可重用的静态资源。 如果您有混合数据类型,那么您可以使用TreeView.ItemTemplateSelector动态选择您想要的DataTemplate

有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.itemtemplateselector.aspx

答案 1 :(得分:0)

根据你的意见,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>

这就是全部!我希望这次我能正确理解你:)

答案 2 :(得分:0)

好吧,我今天小睡了,当我醒来时,我突然意识到答案是什么!这是:

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

答案 3 :(得分:0)

如果您希望在Binding中使用StaticResource,请使用Hillberg's freezable trick