从DataTemplate访问父DataContext
我有一个ListBox
绑定到ViewModel上的子集合。 列表框项目根据父ViewModel上的属性在数据模板中进行样式设置:
<Style x:Key="curveSpeedNonConstantParameterCell">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=DataContext.CurveSpeedMustBeSpecified,
ElementName=someParentElementWithReferenceToRootDataContext}"
Value="True">
<Setter Property="Control.Visibility" Value="Hidden"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
我得到以下输出错误:
System.Windows.Data Error: 39 : BindingExpression path error:
'CurveSpeedMustBeSpecified' property not found on
'object' ''BindingListCollectionView' (HashCode=20467555)'.
BindingExpression:Path=DataContext.CurveSpeedMustBeSpecified;
DataItem='Grid' (Name='nonConstantCurveParametersGrid');
target element is 'TextBox' (Name='');
target property is 'NoTarget' (type 'Object')
因此,如果我将绑定表达式更改为"Path=DataContext.CurrentItem.CurveSpeedMustBeSpecified"
它将起作用,但只有父用户控件的datacontext是BindingListCollectionView
。 这是不可接受的,因为用户控件的其余部分会自动绑定到BindingList
上的CurrentItem
属性。
如何在样式中指定绑定表达式,以便它可以工作,而不管父数据上下文是集合视图还是单个项目?
我在Silverlight的相关源代码中遇到了问题。 搜索和阅读后,我没有找到一个合适的解决方案,没有使用一些额外的绑定库。 但是,这是另一种通过直接引用您知道数据上下文的元素来访问父DataContext的方法。 它使用Binding ElementName
并且工作得很好,只要您尊重自己的命名,并且不会跨组件重复使用templates
/ styles
:
<ItemsControl x:Name="level1Lister" ItemsSource={Binding MyLevel1List}>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content={Binding MyLevel2Property}
Command={Binding ElementName=level1Lister,
Path=DataContext.MyLevel1Command}
CommandParameter={Binding MyLevel2Property}>
</Button>
<DataTemplate>
<ItemsControl.ItemTemplate>
</ItemsControl>
如果将按钮放入Style
/ Template
这也适用:
<Border.Resources>
<Style x:Key="buttonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Button Command={Binding ElementName=level1Lister,
Path=DataContext.MyLevel1Command}
CommandParameter={Binding MyLevel2Property}>
<ContentPresenter/>
</Button>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Border.Resources>
<ItemsControl x:Name="level1Lister" ItemsSource={Binding MyLevel1List}>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding MyLevel2Property}"
Style="{StaticResource buttonStyle}"/>
<DataTemplate>
<ItemsControl.ItemTemplate>
</ItemsControl>
起初我以为父元素的x:Names
不能从模板化的项目中访问,但是由于我没有找到更好的解决方案,我只是尝试了一下,并且它工作正常。
您可以使用RelativeSource
来查找父元素,就像这样 -
Binding="{Binding Path=DataContext.CurveSpeedMustBeSpecified,
RelativeSource={RelativeSource AncestorType={x:Type local:YourParentElementType}}}"
看到这个SO问题关于RelativeSource
更多细节。
我正在寻找如何在WPF中做类似的事情,并且我得到了这个解决方案:
<ItemsControl ItemsSource="{Binding MyItems,Mode=OneWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<RadioButton
Content="{Binding}"
Command="{Binding Path=DataContext.CustomCommand,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type ItemsControl}} }"
CommandParameter="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
我希望这适用于其他人。 我有一个自动设置为ItemsControls的数据上下文,并且此数据上下文具有两个属性: MyItems
(其为集合)和一个命令'CustomCommand'。 由于ItemTemplate
正在使用DataTemplate
,所以上层的DataContext
不能直接访问。 然后,获取父级的DC的解决方法是使用相对路径并按ItemsControl
类型进行筛选。
上一篇: Access parent DataContext from DataTemplate
下一篇: Send an audio stream from Wowza to a speech to text cloud service