求助:在WPF Style中无法访问父级DataContext的问题
这个坑我踩过好多次!WPF里的ContextMenu是个“特殊分子”——它属于独立的可视化树,默认不会继承父级控件(比如DataGrid)的DataContext,所以你直接写Command="???"肯定找不到ViewModel里的命令。给你几个实用的解决方案:
方法1:通过RelativeSource直接绑定到DataGrid的DataContext
这是最直接的方式,直接往上找DataGrid控件,然后取它的DataContext:
<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="{Binding DataContext.DeleteCommand, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" /> </ContextMenu> </Setter.Value> </Setter> </Style> </DataGrid.Resources> </DataGrid>
这里的RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}会帮你找到最近的DataGrid父控件,然后DataContext.DeleteCommand就指向ViewModel里的删除命令了。
方法2:用Tag传递父级DataContext
如果担心RelativeSource层级找错(比如嵌套了多个DataGrid),可以先把DataGrid的DataContext存到DataGridRow的Tag属性里,再让ContextMenu通过PlacementTarget获取:
<DataGrid Name="ReferenceDataGrid" ItemsSource="{Binding Items}" AutoGenerateColumns="False" RowHeaderWidth="0" IsReadOnly="True"> <DataGrid.Resources> <Style TargetType="DataGridRow"> <!-- 先把DataGrid的DataContext存到Row的Tag里 --> <Setter Property="Tag" Value="{Binding DataContext, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" /> <Setter Property="ContextMenu"> <Setter.Value> <ContextMenu> <MenuItem Header="Delete" Command="{Binding PlacementTarget.Tag.DeleteCommand, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}" /> </ContextMenu> </Setter.Value> </Setter> </Style> </DataGrid.Resources> </DataGrid>
PlacementTarget指的是ContextMenu附着的控件(也就是DataGridRow),所以通过它的Tag就能拿到之前存的ViewModel了。
额外提示:绑定命令参数
如果你的Delete命令需要知道要删除哪一行的数据,别忘了加上CommandParameter:
<MenuItem Header="Delete" Command="{Binding DataContext.DeleteCommand, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" CommandParameter="{Binding}" />
这里的{Binding}会自动绑定到当前DataGridRow的DataContext(也就是Items集合里的单个数据项),ViewModel里的命令就能直接拿到要删除的对象了。
内容的提问来源于stack exchange,提问作者TorbenJ
相关产品推荐
相关产品推荐

