WPF 模板绑定到模板化父级的 DataContext
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23481350/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF TemplateBinding to DataContext of templated parent
提问by 15ee8f99-57ff-4f92-890c-b56153
We have four identical popups with grids in four XAML views. I'd like to move that XAML to a template and apply via a Style to to ContentControls in all four of them. The trouble is passing in the source of the items in the grids. We get that from each of four different view models. It's different in each case, the only thing that differs among the four cases. I'll probably end up renaming them consistently, but I'd like to think that's a separate issue.
我们在四个 XAML 视图中有四个相同的带有网格的弹出窗口。我想将该 XAML 移至模板,并通过样式应用于所有四个中的 ContentControl。麻烦在于传递网格中项目的来源。我们从四个不同的视图模型中得到了它。每种情况都不同,唯一不同的是四种情况。我可能最终会始终如一地重命名它们,但我想这是一个单独的问题。
Obviously I don't understand TemplateBinding at all. How do I bind a property of a child of the template to a property of the ContentControl that I'm applying the template to?
显然我根本不了解 TemplateBinding。如何将模板子项的属性绑定到我正在应用模板的 ContentControl 的属性?
Except for the value of the DataSource attribute changing, the XAML for the grid is identical to what works perfectly well when we use it directly.
除了 DataSource 属性的值发生变化之外,网格的 XAML 与我们直接使用时效果很好的相同。
I added the TextBlock just to see if I could bind anything at all. I do get NaNthere.
我添加了 TextBlock 只是为了看看我是否可以绑定任何东西。我确实到了NaN。
<Style x:Key="HistoryPopupContentStyle" TargetType="ContentControl">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{TemplateBinding Width,
diag:PresentationTraceSources.TraceLevel=High}"
Background="White"
Foreground="Black"/>
<dxg:GridControl
DataSource="{Binding RelativeSource={RelativeSource
Path=DataContext,
TraceLevel=High}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
>
<!-- Columns. The grid displays column headers
as desired but with no rows -->
</dxg:GridControl.Columns>
</dxg:GridControl>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<Popup
Name="PopHistory"
DataContext="{Binding Path=HistoryList}"
>
<ContentControl DataContext="{Binding Path=HistoryList}"
Style="{StaticResource HistoryPopupContentStyle}"
Name="Testing"
/>
</Popup>
回答by McGarnagle
You will need to subclass ContentControl(or just Control), so that you can add new dependency properties.
您将需要子类化ContentControl(或只是Control),以便您可以添加新的依赖属性。
public class GridControl : ContentControl
{
// TODO add dependency properties
public GridControl()
{
DefaultStyleKey = typeof(GridControl);
}
}
Add your "Items" dependency property to the above control (type IEnumerable).
将您的“项目”依赖项属性添加到上述控件(类型IEnumerable)。
Next, update your template to target the new type:
接下来,更新您的模板以定位新类型:
<Style x:Key="HistoryPopupContentStyle" TargetType="local:GridControl">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<dxg:GridControl ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=local:GridControl},Path=Items}" />
Alternately, you could set the "Template" instead of the "ContentTemplate". This would be when you use TemplateBinding:
或者,您可以设置“模板”而不是“内容模板”。这将是您使用时TemplateBinding:
<Style x:Key="HistoryPopupContentStyle" TargetType="local:GridControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:GridControl">
<dxg:GridControl ItemsSource="{TemplateBinding Items}" />
Use it by binding the Itemsproperty to your source items:
通过将Items属性绑定到源项来使用它:
<local:GridControl Style="{StaticResource HistoryPopupContentStyle}"
Items="{Binding Path=HistoryList}" />
You could also skip creating a subclass altogether, and just use the Contentproperty of ContentControlto stash the items:
您也可以完全跳过创建子类,只需使用 的Content属性ContentControl来存储项目:
<Style x:Key="HistoryPopupContentStyle" TargetType="ContentControl">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<dxg:GridControl ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=local:GridControl},Path=Content}" />
Or using the Template / TemplateBinding approach
或者使用 Template / TemplateBinding 方法
<Style x:Key="HistoryPopupContentStyle" TargetType="ContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<dxg:GridControl ItemsSource="{TemplateBinding Content}" />
Use like this:
像这样使用:
<ContentControl Style="{StaticResource HistoryPopupContentStyle}"
Content="{Binding Path=HistoryList}" />

