You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF MVVM实现:点击按钮增减DataGrid单元格数值

实现DataGrid单元格数值的加减按钮功能

没问题,这是WPF MVVM开发里非常常见的场景,我来一步步带你实现这个加减数值的功能:


第一步:完善模型与ViewModel,实现属性变更通知

WPF的UI更新依赖INotifyPropertyChanged接口,所以你的ProductModel和ViewModel都需要实现这个接口,否则属性变化后UI不会自动刷新。

补全ProductModel代码

public class ProductModel : INotifyPropertyChanged
{
    private decimal _productQuantity;
    public decimal Product_Quantity
    {
        get => _productQuantity;
        set
        {
            if (_productQuantity != value)
            {
                _productQuantity = value;
                OnPropertyChanged(nameof(Product_Quantity));
            }
        }
    }

    // 这里放你的其他属性...

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

完善ViewModel(添加命令+补全属性)

我们需要给ViewModel添加加减命令,同时补全SelectedRow的setter并实现属性变更通知:

public class YourViewModel : INotifyPropertyChanged
{
    private ObservableCollection<ProductModel> _products;
    public ObservableCollection<ProductModel> Products
    {
        get => _products;
        set
        {
            _products = value;
            OnPropertyChanged(nameof(Products));
        }
    }

    private ProductModel _selectedRow;
    public ProductModel SelectedRow
    {
        get => _selectedRow;
        set
        {
            _selectedRow = value;
            OnPropertyChanged(nameof(SelectedRow));
        }
    }

    // 加减命令
    public ICommand IncrementCommand { get; }
    public ICommand DecrementCommand { get; }

    public YourViewModel()
    {
        Products = new ObservableCollection<ProductModel>();
        // 初始化命令(如果没用MVVM框架,就用下面的自定义RelayCommand)
        IncrementCommand = new RelayCommand(ExecuteIncrement, CanExecuteModify);
        DecrementCommand = new RelayCommand(ExecuteDecrement, CanExecuteModify);
    }

    private void ExecuteIncrement()
    {
        if (SelectedRow != null)
        {
            SelectedRow.Product_Quantity += 1;
        }
    }

    private void ExecuteDecrement()
    {
        // 可以加个最小值限制,比如不能小于0
        if (SelectedRow != null && SelectedRow.Product_Quantity > 0)
        {
            SelectedRow.Product_Quantity -= 1;
        }
    }

    // 控制命令是否可用(只有选中行时按钮才可用)
    private bool CanExecuteModify()
    {
        return SelectedRow != null;
    }

    // INotifyPropertyChanged实现
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

自定义RelayCommand(如果没使用MVVM框架)

如果你的项目没用到Prism、MVVM Light这类框架,需要自己实现一个简单的RelayCommand来支持命令绑定:

public class RelayCommand : ICommand
{
    private readonly Action _execute;
    private readonly Func<bool> _canExecute;

    public RelayCommand(Action execute, Func<bool> canExecute = null)
    {
        _execute = execute ?? throw new ArgumentNullException(nameof(execute));
        _canExecute = canExecute;
    }

    public event EventHandler CanExecuteChanged
    {
        add => CommandManager.RequerySuggested += value;
        remove => CommandManager.RequerySuggested -= value;
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute == null || _canExecute();
    }

    public void Execute(object parameter)
    {
        _execute();
    }
}

第二步:XAML实现(两种方案任选)

方案一:每行都带加减按钮(嵌入DataGrid列)

如果想让DataGrid的每一行都有自己的加减按钮,可以用DataGridTemplateColumn来实现:

<DataGrid ItemsSource="{Binding Products}" 
          SelectedItem="{Binding SelectedRow}"
          AutoGenerateColumns="False">
    <DataGrid.Columns>
        <!-- 其他业务列 -->
        <DataGridTextColumn Header="商品数量" Binding="{Binding Product_Quantity}" />
        
        <DataGridTemplateColumn Header="操作">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" Spacing="5">
                        <Button Content="+" 
                                Command="{Binding DataContext.IncrementCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}"
                                CommandParameter="{Binding}" />
                        <Button Content="-" 
                                Command="{Binding DataContext.DecrementCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}"
                                CommandParameter="{Binding}" />
                    </StackPanel>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

这种情况下,需要把ViewModel的命令改成支持参数的泛型版本,调整一下:

// 修改ViewModel的命令初始化
IncrementCommand = new RelayCommand<ProductModel>(ExecuteIncrementWithParam);
DecrementCommand = new RelayCommand<ProductModel>(ExecuteDecrementWithParam);

// 对应的执行方法
private void ExecuteIncrementWithParam(ProductModel product)
{
    product.Product_Quantity += 1;
}

private void ExecuteDecrementWithParam(ProductModel product)
{
    if (product.Product_Quantity > 0)
    {
        product.Product_Quantity -= 1;
    }
}

// 泛型版RelayCommand
public class RelayCommand<T> : ICommand
{
    private readonly Action<T> _execute;
    private readonly Predicate<T> _canExecute;

    public RelayCommand(Action<T> execute, Predicate<T> canExecute = null)
    {
        _execute = execute ?? throw new ArgumentNullException(nameof(execute));
        _canExecute = canExecute;
    }

    public event EventHandler CanExecuteChanged
    {
        add => CommandManager.RequerySuggested += value;
        remove => CommandManager.RequerySuggested -= value;
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute == null || _canExecute((T)parameter);
    }

    public void Execute(object parameter)
    {
        _execute((T)parameter);
    }
}

方案二:全局加减按钮(操作选中行)

如果只需要页面上的全局按钮来操作当前选中的行,XAML会更简单:

<StackPanel Margin="10">
    <StackPanel Orientation="Horizontal" Spacing="10" Margin="0 0 0 10">
        <Button Content="增加数量" 
                Command="{Binding IncrementCommand}"/>
        <Button Content="减少数量" 
                Command="{Binding DecrementCommand}"/>
    </StackPanel>
    
    <DataGrid ItemsSource="{Binding Products}" 
              SelectedItem="{Binding SelectedRow}"
              AutoGenerateColumns="True"/>
</StackPanel>

这个方案直接用第一步里的非参数版命令即可,没有选中行时按钮会自动灰掉。


关键注意点

  • 必须实现INotifyPropertyChanged:这是WPF UI自动更新的核心,模型和ViewModel的属性变更都要触发PropertyChanged事件。
  • 用ICommand实现逻辑分离:MVVM模式下尽量避免在代码后台直接操作UI,通过命令绑定把业务逻辑放在ViewModel里。
  • 命令的可执行状态:通过CanExecute方法控制按钮的可用状态,提升用户体验。

内容的提问来源于stack exchange,提问作者Usman Ali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:38:24