从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是a BindingListCollectionView。这是不可接受的,因为其余的用户控件会自动绑定到CurrentItemon的属性BindingList。


如何在样式内指定绑定表达式,以便无论父数据上下文是集合视图还是单个项目,绑定表达式都可以工作?


FFIVE
浏览 1009回答 3
3回答

MMMHUHU

我在Silverlight中遇到了相对来源的问题。搜索和阅读后,如果不使用其他绑定库,我找不到合适的解决方案。但是,这是通过直接引用您知道数据上下文的元素来获得对父DataContext的访问的另一种方法。它使用Binding ElementName和工作的很好,只要你尊重自己的命名,不具备重重用templates/ styles跨组件:<ItemsControl x:Name="level1Lister" ItemsSource={Binding MyLevel1List}>&nbsp; <ItemsControl.ItemTemplate>&nbsp; &nbsp; <DataTemplate>&nbsp; &nbsp; &nbsp; <Button Content={Binding MyLevel2Property}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Command={Binding ElementName=level1Lister,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Path=DataContext.MyLevel1Command}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CommandParameter={Binding MyLevel2Property}>&nbsp; &nbsp; &nbsp; </Button>&nbsp; &nbsp; <DataTemplate>&nbsp; <ItemsControl.ItemTemplate></ItemsControl>如果你把按钮进入这也适用Style/ Template:<Border.Resources>&nbsp; <Style x:Key="buttonStyle" TargetType="Button">&nbsp; &nbsp; <Setter Property="Template">&nbsp; &nbsp; &nbsp; <Setter.Value>&nbsp; &nbsp; &nbsp; &nbsp; <ControlTemplate TargetType="Button">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Button Command={Binding ElementName=level1Lister,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Path=DataContext.MyLevel1Command}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CommandParameter={Binding MyLevel2Property}>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<ContentPresenter/>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </Button>&nbsp; &nbsp; &nbsp; &nbsp; </ControlTemplate>&nbsp; &nbsp; &nbsp; </Setter.Value>&nbsp; &nbsp; </Setter>&nbsp; </Style></Border.Resources><ItemsControl x:Name="level1Lister" ItemsSource={Binding MyLevel1List}>&nbsp; <ItemsControl.ItemTemplate>&nbsp; &nbsp; <DataTemplate>&nbsp; &nbsp; &nbsp; <Button Content="{Binding MyLevel2Property}"&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Style="{StaticResource buttonStyle}"/>&nbsp; &nbsp; <DataTemplate>&nbsp; <ItemsControl.ItemTemplate></ItemsControl>最初,我认为x:Names无法从模板项中访问父元素,但是由于找不到更好的解决方案,因此我尝试了一下,并且工作正常。

宝慕林4294392

我正在搜索如何在WPF中执行类似操作,并且得到了以下解决方案:<ItemsControl ItemsSource="{Binding MyItems,Mode=OneWay}"><ItemsControl.ItemsPanel>&nbsp; &nbsp; <ItemsPanelTemplate>&nbsp; &nbsp; &nbsp; &nbsp; <StackPanel Orientation="Vertical" />&nbsp; &nbsp; </ItemsPanelTemplate></ItemsControl.ItemsPanel><ItemsControl.ItemTemplate>&nbsp; &nbsp; <DataTemplate>&nbsp; &nbsp; &nbsp; &nbsp; <RadioButton&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Content="{Binding}"&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Command="{Binding Path=DataContext.CustomCommand,&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RelativeSource={RelativeSource Mode=FindAncestor,&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AncestorType={x:Type ItemsControl}} }"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CommandParameter="{Binding}" />&nbsp; &nbsp; </DataTemplate></ItemsControl.ItemTemplate>我希望这对其他人也有用。我有一个自动设置为ItemsControls的数据上下文,该数据上下文具有两个属性:MyItems-这是一个集合-和一个命令'CustomCommand'。由于ItemTemplate使用DataTemplate,DataContext无法直接访问上层的。然后,获取父级DC的解决方法是使用相对路径并按ItemsControl类型进行过滤。

慕勒3428872

RelativeSource与ElementName这两种方法可以达到相同的结果,相对榨汁Binding="{Binding Path=DataContext.MyBindingProperty,&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RelativeSource={RelativeSource AncestorType={x:Type Window}}}"此方法在可视树中查找Window类型的控件(在此示例中),找到它后,您基本上可以DataContext使用来访问它Path=DataContext....。关于此方法的优点是,您无需与名称绑定,并且名称是动态的,但是,对可视化树所做的更改可能会影响此方法,甚至可能破坏该方法。元素名称Binding="{Binding Path=DataContext.MyBindingProperty, ElementName=MyMainWindow}这个方法指的是一个固体静态对象Name,只要您的示波器可以看到它就可以了,您应该坚持使用命名约定,不要破坏该方法。该方法很简单,您需要指定一个Name="..."代表您的Window / UserControl。尽管这三种类型(RelativeSource, Source, ElementName)都可以执行相同的操作,但是根据下面的MSDN文章,每种类型最好在各自的专业领域中使用。在页面底部的表中找到每个内容的简要说明以及指向更多详细信息的链接。
打开App,查看更多内容
随时随地看视频慕课网APP