运行 编辑数据网格上的单元格后的方法

Run a method after editing a cell on a datagrid

我正在使用 WPF 和 CaliburnMicro 来绑定数据。每次我完成编辑单元格时,我都想 运行 一个 Add() 方法,但问题是数据网格的 属性 不执行它。

这是我的代码:

<Window x:Class="DataGrid_NotifyOfPropertyChanged.Views.ShellView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:DataGrid_NotifyOfPropertyChanged.Views"
    mc:Ignorable="d"
    Title="ShellView" Height="450" Width="800">
<Grid>
    <DataGrid x:Name="Numbers" CanUserAddRows="False"/>
</Grid>
public class NumbersModel
{
    public int Number { get; set; }
}

ShellViewModel

public class ShellViewModel: Screen
{
    public ShellViewModel()
    {
        Numbers.Add(new NumbersModel { Number = 1 });
        Numbers.Add(new NumbersModel { Number = 2 });
    }

    private BindableCollection<NumbersModel> _numbers = new BindableCollection<NumbersModel>();

    public BindableCollection<NumbersModel> Numbers
    {
        get { return _numbers; }
        set { 
            _numbers = value;
            Add();
        }
    }

    public void Add()
    {
        double result = 0;
        foreach(var i in _numbers.ToList())
        {
            result += i.Number;
        }
        MessageBox.Show(result.ToString());
    }
}

您必须让 NumbersModel 实现 INotifyPropertyChanged 接口。
这样您就可以在 属性 更改时收到通知。通常,您 总是 必须在每个用作绑定源的 class 上实现此接口。
没有这个接口数据绑定也可以工作,但是性能会急剧下降。对于具有许多绑定的应用程序,这将是一个问题。

解决办法是监听NumbersModel.Number的属性变化。因此,我推出了一个专门的活动 NumberChanged.
事件 NumberChanged 是可选的。也可以监听PropertyChanged然后用switch语句通过属性名字过滤需要的属性。我认为专用事件显着提高了可读性和对上下文的理解,而不是混乱的 switch 块。

为防止删除项目时发生内存泄漏,您必须取消订阅您正在收听的 NumbersModel 的每个事件。
因此,您还需要监听 Numbers 集合的 CollectionChanged 事件:

NumbersModel.cs

public class NumbersModel : INotifyPropertyChanged
{
  private int number;
  public int Number
  {
    get => this.number;
    set
    {
      if (value == this.number)
      {
        return;
      }

      this.number = value;
      OnPropertyChanged();
      OnNumberChanged();
    }
  }

  public event EventHandler NumberChanged;
  public event PropertyChangedEventHandler PropertyChanged;

  protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
  {
    this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  }

  protected virtual void OnNumberChanged()
  {
    this.NumberChanged?.Invoke(this, EventArgs.Empty);
  }
}

ShellViewModel.cs

public class ShellViewModel : Screen
{
  public ShellViewModel()
  {
    this.Numbers = new BindableCollection<NumbersModel>();
    this.Numbers.Add(new NumbersModel {Number = 1});
    this.Numbers.Add(new NumbersModel {Number = 2});
  }

  public void Add()
  {
    double result = this._numbers.Sum(numbersModel => numbersModel.Number);
    MessageBox.Show(result.ToString());
  }

  private BindableCollection<NumbersModel> _numbers;
  public BindableCollection<NumbersModel> Numbers
  {
    get => this._numbers;
    set
    {
      // Unsubscribe from old collection
      if (this.Numbers != null)
      {
        this.Numbers.CollectionChanged -= OnCollectionChanged;
      }

      this._numbers = value;

      // Subscribe to new collection
      if (this.Numbers != null)
      {
        this.Numbers.CollectionChanged += OnCollectionChanged;
        Add();
      }
    }
  }

  private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
  {
    switch (e.Action)
    {
      case NotifyCollectionChangedAction.Add:
      {
        foreach (NumbersModel newItem in e.NewItems.Cast<NumbersModel>())
        {
          newItem.NumberChanged += OnNumberChanged;
        }

        break;
      }
      case NotifyCollectionChangedAction.Remove:
      case NotifyCollectionChangedAction.Reset:
      {
        foreach (NumbersModel newItem in e.OldItems.Cast<NumbersModel>())
        {
          newItem.NumberChanged -= OnNumberChanged;
        }

        break;
      }
    }
  }

  private void OnNumberChanged(object sender, EventArgs e)
  {
    Add();
  }
}

I want to run an Add() method every time I finished editing a cell

使用 Caliburn.Micro 执行此操作的方法是使用 EventTriggerActionMessage 来处理 CellEditEnding 事件:

 <DataGrid x:Name="Numbers" CanUserAddRows="False"
     cal:Message.Attach="[Event CellEditEnding] = [Action Add()]" />