我有一个ListBox
绑定到ViewModel上的一个子集合。列表框项在DataTemplate中的样式基于父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
的属性。
如何在样式内指定绑定表达式,以便无论父数据上下文是集合视图还是单个项,它都能正常工作?
7条答案
按热度按时间gt0wga4j1#
我在Silverlight中的相对源代码上遇到了问题。在搜索和阅读之后,如果不使用一些额外的绑定库,我没有找到合适的解决方案。但是,这里有另一种方法,通过直接引用您知道数据上下文的元素来访问父DataContext。它使用
Binding ElementName
,工作得很好。只要您尊重自己的命名,并且不在组件之间大量重用templates
/styles
:如果您将按钮放入
Style
/Template
中,也可以执行此操作:一开始我认为父元素的
x:Names
不能从模板项中访问,但是由于我没有找到更好的解决方案,我只是尝试了一下,它工作得很好。jqjz2hbq2#
可以使用
RelativeSource
来查找父元素,如下所示-有关
RelativeSource
的更多详细信息,请参见this SO question。agxfikkp3#
相对源与元素名称
这两种方法可以实现相同的结果,
相对源
此方法在可视化树中查找Window类型的控件(在此示例中),当它找到它时,您基本上可以使用
Path=DataContext....
访问它的DataContext
。此方法的优点是您不需要绑定到名称,并且它是一种动态的,但是,对可视化树所做的更改可能会影响此方法,甚至可能会破坏它。元素名称
这个方法引用了一个固定的静态
Name
,所以只要你的作用域可以看到它,你就可以了。当然,你应该坚持你的命名约定,不要破坏这个方法。这个方法非常简单,你所需要的就是为你的Window/UserControl指定一个Name="..."
。尽管所有三种类型(
RelativeSource, Source, ElementName
)都能够完成相同的任务,但是根据下面的MSDN文章,每种类型最好都用于各自的专业领域。How to: Specify the Binding Source
在页面底部的表格中找到每个选项的简要说明以及指向更详细选项的链接。
k4emjkb14#
我正在搜索如何在WPF中做类似的事情,我得到了这个解决方案:
我希望这对其他人有用。我有一个自动设置为ItemsControls的数据上下文,这个数据上下文有两个属性:
MyItems
(一个集合)和一个命令“CustomCommand”。由于ItemTemplate
正在使用DataTemplate
,因此无法直接访问更高级别的DataContext
。因此,获取父级DC的解决方法是使用相对路径并按ItemsControl
类型筛选。hvvq6cgz5#
问题是DataTemplate不是应用于它的元素的一部分。
这意味着如果你绑定到模板你就绑定到了没有上下文的东西。
然而,如果你把一个元素放在模板中,那么当这个元素被应用到父元素时,它会获得一个上下文,然后绑定就可以工作了
所以这行不通
但这个很好用
因为应用数据模板后,组框将被放置在父项中,并且将有权访问其上下文
因此,您所要做的就是从模板中删除样式并将其移动到模板中的元素中
注意itemscontrol的上下文是项而不是控件,即ComboBoxItem表示ComboBox而不是ComboBox本身,在这种情况下,您应该使用控件ItemContainerStyle
yhqotfr86#
是的,你可以按照尤文的建议使用
ElementName=Something
来解决它。但是!
如果子元素(您在其上使用这种绑定)是一个用户控件,而该用户控件使用的元素名称与您在父控件中指定的元素名称相同,则绑定将转到错误的对象!!
我知道这篇文章不是一个解决方案,但我认为每个在绑定中使用ElementName的人都应该知道这一点,因为它可能是一个运行时错误。
4si2a6ki7#
也可以通过
.
执行。使用此操作符,您可以访问Source
。此处可以选择使用句点(.)路径绑定到当前源。例如,Text="{Binding}”等效于Text="{Binding Path=.}"。
例如,我喜欢这样做(将
DataContext
放入Tag
中,然后访问parentDataContext
):资源字典.xaml:
主窗口.xaml:
主窗口.xaml.cs: