不能在样式中使用父级的DataContext

时间:2018-04-03 11:28:39

标签: c# wpf binding

我在Style中访问特定的DataContext时遇到了一些问题 我有CatalogItem.joins(:item, :catalog). where(items: { id: 4 }).pluck(:position).first 定义如下:

DataGrid

包含此<DataGrid Name="ReferenceDataGrid" ItemsSource="{Binding Items}" AutoGenerateColumns="False" RowHeaderWidth="0" IsReadOnly="True"> <DataGrid.Resources> <Style TargetType="DataGridRow"> <Setter Property="ContextMenu"> <Setter.Value> <ContextMenu> <MenuItem Header="Delete" Command="???" /> </ContextMenu> </Setter.Value> </Setter> </Style> </DataGrid.Resources> ... 的{​​{1}}的{​​{1}}属性设置为

DataContext

我想将Page绑定到DataGrid并尝试了几种不同的方法来执行此操作:

  • DataContext="{Binding RelativeSource={RelativeSource Self}}"
  • RelayCommand //页面元素的名称设置为Root
  • MenuItem
  • Command="{Binding DeleteCommand}"

我在Command="{Binding ElementName=Root, Path=DeleteCommand}"的命令处理程序中设置了断点,但上面没有任何变化。

假设Command="{Binding ElementName=Root, Path=DataContext.DeleteCommand}"包含Command="{Binding Path=DataContext.DeleteCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}}"类型的元素 如果我在DeleteCommand中定义命令,处理程序会被触发,所以看起来无论我上面做了什么,每个Items的{​​{1}}似乎都是列表元素本身。

知道该怎么办吗?

修改
我还尝试将Foo提取到一个单独的类中,并引用此而不是Foo,因为我认为列表元素可能使用DataContext作为DataGridRow而不是DataContext它指的是实例。不幸的是我错了。

2 个答案:

答案 0 :(得分:1)

由于您只对一个地方的命令感兴趣,因此您可能会发现另一种有用的方法。 将contextmenu定义为可以获取该datacontext的资源,然后将其应用于datagrid行。 我已经在最初用于其他目的的样本上做了这个,所以我的对象和东西是不同的。

<DataGrid 
    ItemsSource="{Binding Users}" 
    Background="White" 
    Name="dg"
    SelectedItem="{Binding SelectedUser}"
          >
    <DataGrid.Resources>
        <ContextMenu x:Key="dgContextMenu"
                     DataContext="{Binding DataContext, RelativeSource={RelativeSource AncestorType=DataGrid}}">
            <MenuItem Header="Up" Command="{Binding UpCommand}" />
        </ContextMenu>
    </DataGrid.Resources>
    <DataGrid.RowStyle>
        <Style TargetType="{x:Type DataGridRow}">
            <Setter Property="ContextMenu" Value="{StaticResource dgContextMenu}"/>

DataContext继承可视树,因此datagrid获取与页面或窗口相同的datacontext或其中的任何内容。 我的contextmenu实际上是在datagrid中,可以获取它的datacontext。

我还绑定了selecteditem,因此我可以使用它来确定点击了哪个特定行。

在窗口的viewmodel中,我有一个命令“UpCommand”,它使用所选用户的属性。

    public RelayCommand UpCommand { get; set; }
    public MainWindowViewModel()
    {
          UpCommand = new RelayCommand(UpExecute);
    }
    public User SelectedUser { get; set; }
    private void UpExecute()
    {
        MessageBox.Show($"You Upped {SelectedUser.Title}");
    }

您可以从用户中删除所选用户,或使用它的ID删除数据库中的记录或删除要执行的操作。

答案 1 :(得分:0)

<ContextMenu  DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}">
    <MenuItem Header="Delete"  Command="{Binding DataContext.DeleteCommand}" />
</ContextMenu>

正如您在回答重复问题时所看到的那样,问题是:

  

ContextMenu在可视树之外

如果您不想将DeleteCommand放入Items中的条目,而不是Source Binding x:Reference<DataGrid Name="ReferenceDataGrid" ItemsSource="{Binding Items}" AutoGenerateColumns="False" RowHeaderWidth="0" IsReadOnly="True"> <DataGrid.Resources> <Style TargetType="DataGridRow"> <Setter Property="ContextMenu"> <Setter.Value> <ContextMenu DataContext="{Binding Path=DataContext, Source={x:Reference ReferenceDataGrid}}"> <MenuItem Header="Delete" Command="{Binding DeleteCommand}" /> </ContextMenu> </Setter.Value> </Setter> </Style> </DataGrid.Resources>

<div style={{ display: 'flex', flexDirection: 'column' }}>

</div>