.net - 从 DataTemplate 访问父 DataContext

标签 .net wpf xaml data-binding datatemplate

我有一个 ListBox,它绑定(bind)到 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')

因此,如果我将绑定(bind)表达式更改为 "Path=DataContext.CurrentItem.CurveSpeedMustBeSpecified" 它就可以工作,但前提是父用户控件的 DataContext 是 BindingListCollectionView。这是 Not Acceptable ,因为用户控件的其余部分会自动绑定(bind)到 BindingList 上的 CurrentItem 的属性。

如何在样式内指定绑定(bind)表达式,以便无论父数据上下文是 Collection View 还是单个项目,它都可以正常工作?

最佳答案

我在使用 Silverlight 中的相对源时遇到了问题。经过搜索和阅读后,如果不使用一些额外的绑定(bind)库,我没有找到合适的解决方案。但是,这是另一种获取父 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 无法从模板项中访问,但由于我没有找到更好的解决方案,所以我只是尝试了一下,效果很好。

关于.net - 从 DataTemplate 访问父 DataContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3404707/

相关文章:

c# - 继承 .net 类

c# - ActiveX 的 .NET 使用者抛出 TargetParameterCountException

c# - 标签式浏览器 CefSharp

c# - 组合框无法准确获取数据库值

wpf - 应用程序图标在任务栏中正确,但在开始菜单中不正确?

c# - 我的深拷贝不是真正的深拷贝

C# - 用户设置损坏

c# - 在 UWP 应用程序中通过键盘交互修改行的可见性

c# - BitmapImage 与 ImageBrush 的性能

c# - UWP SolidColorBrush - 应用程序调用为不同线程异常编码的接口(interface)