C# 无法从样式中使用父级的DataContext
从样式中访问特定DataContext时遇到一些问题。C# 无法从样式中使用父级的DataContext,c#,wpf,binding,C#,Wpf,Binding,从样式中访问特定DataContext时遇到一些问题。 我有一个DataGrid定义如下: <DataGrid Name="ReferenceDataGrid" ItemsSource="{Binding Items}" AutoGenerateColumns="False" RowHeaderWidth="0" IsReadOnly="True"> <DataGrid.Resources> <Style TargetType="DataGr
我有一个
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>
...
我想将RelayCommand
绑定到菜单项
,并尝试了几种不同的方法:
Command=“{Binding DeleteCommand}”
//页面元素的名称设置为RootCommand=“{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
包含Foo
类型的元素如果我在
Foo
中定义该命令,则会触发处理程序,因此无论我在上面做了什么,每个DataGridRow
的DataContext
似乎都是列表元素本身
你知道怎么办吗
编辑:我还尝试将
DataContext
提取到一个单独的类中,并引用该类而不是相对Self
,因为我认为列表元素可能使用相对Self
作为其DataContext
而不是它引用的页面
实例。不幸的是,我错了。因为您只对一个地方的命令感兴趣,所以有另一种方法可以做到这一点,您可能会发现它很有用。
<ContextMenu DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Delete" Command="{Binding DataContext.DeleteCommand}" />
</ContextMenu>
将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}"/>
您可以从用户中删除所选用户,或者使用其ID从数据库中删除记录,或者执行任何删除操作。可能重复的Nope也不起作用。也许我必须做一些不同的事情,因为我使用的是样式而不是数据模板?你会只使用与DataGrid相同的datacontext中的命令吗?@Andy到目前为止,我每个页面/窗口都只有一个datacontext等。我真的不想用这些东西把模型类弄乱,所以我将它们存储在页面的datacontext中。我还需要更新DataContext中的几个其他属性,以便将其中的部分提取到单独的属性中不会带来任何好处实际上。。。这是件好事。我将发布一个解决方案。我已经尝试过这个解决方案,但它不像我在评论中说的那样有效。它对我有效。是否确实在对象中有GridRowDataContextDeleteCmd,该对象是DataGridRow的DataContext?请查看设置了
ContextMenu
的DataContext
。我正在尝试重现该问题,它显示错误4。我还使用PresentationTraceSources.TraceLevel=High
尝试了您的解决方案,但没有效果。我认为事件处理程序可能是这里的解决方案。@Rekshino我复制粘贴了您的代码,以确保我这边没有输入错误,但它仍然不起作用。命令实例已存在。我在DataGrid旁边创建了一个按钮,让它成功触发这个命令,所以我假设命令实例本身不是问题所在。
<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>
<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}"/>
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}");
}