Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在数据网格上编辑单元格后运行方法_C#_Wpf_Datagrid_Caliburn.micro - Fatal编程技术网

C# 在数据网格上编辑单元格后运行方法

C# 在数据网格上编辑单元格后运行方法,c#,wpf,datagrid,caliburn.micro,C#,Wpf,Datagrid,Caliburn.micro,我使用WPF和CaliburnMicro绑定数据。我想在每次编辑完单元格后都运行Add()方法,但问题是datagrid的属性没有执行它 这是我的密码: <Window x:Class="DataGrid_NotifyOfPropertyChanged.Views.ShellView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x=&

我使用WPF和CaliburnMicro绑定数据。我想在每次编辑完单元格后都运行Add()方法,但问题是datagrid的属性没有执行它

这是我的密码:

<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>
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());
    }
}
公共类ShellViewModel:屏幕
{
公共ShellViewModel()
{
Add(新的NumbersModel{Number=1});
Add(新的NumbersModel{Number=2});
}
私有BindableCollection_numbers=新的BindableCollection();
公共可绑定集合编号
{
获取{return\u numbers;}
集合{
_数字=数值;
添加();
}
}
公共无效添加()
{
双结果=0;
foreach(变量i在_numbers.ToList()中)
{
结果+=i.编号;
}
Show(result.ToString());
}
}

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

解决方案是侦听
NumbersModel.Number
的属性更改。因此,我引入了一个专门的事件
NumberChanged

事件
NumberChanged
是可选的。您还可以侦听
PropertyChanged
,然后使用
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);
  }
}
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();
  }
}
ShellViewModel.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);
  }
}
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();
  }
}
公共类ShellViewModel:屏幕
{
公共ShellViewModel()
{
this.Numbers=new BindableCollection();
this.Numbers.Add(newnumbersmodel{Number=1});
this.Numbers.Add(newnumbersmodel{Number=2});
}
公共无效添加()
{
double result=this.\u numbers.Sum(numbersModel=>numbersModel.Number);
Show(result.ToString());
}
私人BindableCollection\u编号;
公共可绑定集合编号
{
get=>这个;
设置
{
//取消订阅旧收藏
如果(this.Numbers!=null)
{
this.Numbers.CollectionChanged-=OnCollectionChanged;
}
这是一个数值;
//订阅新收藏
如果(this.Numbers!=null)
{
this.Numbers.CollectionChanged+=OnCollectionChanged;
添加();
}
}
}
CollectionChanged的私有void(对象发送方,NotifyCollectionChangedEventArgs e)
{
开关(电动)
{
案例NotifyCollectionChangedAction。添加:
{
foreach(e.NewItems.Cast()中的NumbersModel newItem)
{
newItem.NumberChanged+=OnNumberChanged;
}
打破
}
案例NotifyCollectionChangedAction。删除:
案例通知CollectionChangedAction.Reset:
{
foreach(e.OldItems.Cast()中的NumberModel newItem)
{
newItem.NumberChanged-=OnNumberChanged;
}
打破
}
}
}
私有void OnNumberChanged(对象发送方,事件参数e)
{
添加();
}
}
每次编辑完单元格后,我都要运行
Add()
方法

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

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


您可以将逻辑放在数字设置器中。您应该使用更仔细的属性命名。始终在viewmodels上更改jmplement INOTIFYPROPERTY。我已尝试过此操作,但输出不是我所期望的。假设我有两个实例(Number=1和Number=2)。更新datagrid中绑定到Number=1的单元格,并将其替换为2,然后执行Add()方法,结果是3而不是4。我在这里做错了什么吗?如何以及何时更新源属性是另一个主题。如果您有其他问题,请提出新问题。您最初的问题是关于如何“每次编辑完单元格后都运行Add()方法”,是吗?很明显,您不理解“编辑完单元格”。从输出判断,单元格根本没有被编辑。