WPF DataGrid内Button的Command属性绑定错误求助
在WPF的DataGrid中嵌入Button,DataGrid的ItemsSource绑定到实体类集合,希望点击Button时调用ViewModel中的GetSettingsCommand,但运行时出现绑定错误。其他非DataGrid内的Button可正常调用该命令,DataGrid数据显示正常,视图与ViewModel的其他绑定也正常,仅该Button功能失效。
相关代码
XAML代码
<DataGrid Name="gridSettingsData" FontSize="13" BorderThickness="0" AutoGenerateColumns="False" CanUserAddRows="False" CanUserReorderColumns="False" SelectedItem="{Binding SelectedSettingsStatus, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding lstDetailedSettingsStatus, UpdateSourceTrigger=PropertyChanged}" ScrollViewer.CanContentScroll="True" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" > <DataGrid.Columns> <DataGridTextColumn IsReadOnly="True" Binding="{Binding Path=FileType}" ClipboardContentBinding="{x:Null}" Header="FileType" Width="160" /> <DataGridTextColumn IsReadOnly="True" Binding="{Binding Path=FileStatus}" ClipboardContentBinding="{x:Null}" Header="FileStatus" Width="580" /> <DataGridTextColumn IsReadOnly="True" Binding="{Binding Path=ExpectedVersion}" ClipboardContentBinding="{x:Null}" Header="ExpectedVersion" Width="120" /> <DataGridTextColumn IsReadOnly="True" Binding="{Binding Path=LastLoadedVersion}" ClipboardContentBinding="{x:Null}" Header="LastLoadedVersion" Width="120" /> <DataGridTemplateColumn Header="View" Width="50"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <Button Content="View" Command="{Binding GetSettingsCommand, RelativeSource={RelativeSource AncestorType=viewmodels:vmProgramming}}" CommandParameter="{Binding ElementName=gridSettingsData, Path=SelectedItem}" > </Button > </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid>
ViewModel代码
public class vmProgramming : BaseViewModel, IPageViewModel { public ICommand GetSettingsCommand { get; private set; } public vmProgramming() { // 其他初始化代码... GetSettingsCommand = new CommunityToolkit.Mvvm.Input.RelayCommand<object>(GetSettings); } private async void GetSettings(object obj) { // 业务逻辑代码,包含异步操作... } }
解决方案
核心问题
DataGrid的CellTemplate内部的数据上下文是当前行的实体类对象,而非ViewModel。原代码中用RelativeSource={RelativeSource AncestorType=viewmodels:vmProgramming}无法找到ViewModel,因为ViewModel是视图的DataContext,不属于可视树的控件类型。
修正步骤
修改Command绑定,指向视图的DataContext
选择以下两种方式之一:方式一:通过RelativeSource查找视图容器
如果DataGrid所在的视图是Window,修改Button的Command绑定:Command="{Binding DataContext.GetSettingsCommand, RelativeSource={RelativeSource AncestorType=Window}}"若DataGrid在UserControl中,将
AncestorType改为UserControl。方式二:通过ElementName绑定视图
给视图(Window/UserControl)设置x:Name="root",然后绑定:Command="{Binding DataContext.GetSettingsCommand, ElementName=root}"
优化CommandParameter(可选)
原代码绑定的是DataGrid的选中项,若希望点击当前行Button时直接传递当前行的实体,可简化为:CommandParameter="{Binding}"
验证
修改后,Button的Command将正确指向ViewModel中的GetSettingsCommand,点击Button会触发GetSettings方法,参数为当前行的实体对象(若使用{Binding})。
内容的提问来源于stack exchange,提问作者donsayTT

