【问题标题】:How to stop INotify from updating twice?如何阻止 INotify 更新两次?
【发布时间】:2017-08-20 07:08:00
【问题描述】:

我正在更新Datagrid,当用户输入一个已经存在的数字时,我想通知用户该数字已经存在,然后从datagrid 中清除该值。

我知道为什么会发生这种情况,但我不知道如何阻止这种情况或如何解决。

这是非常简化的代码:首先使用 EF 代码和 MVVM 模型。

public partial class StaffMasterData
{
    public System.Guid Id { get; set; } // ID (Primary key)        
    public int? StaffNo { get; set; } // StaffNo        

    public StaffMasterData()
    {
        InitializePartial();
    }

    partial void InitializePartial();        
}

StaffMasterData 的实体扩展类:

public partial class StaffMasterData : INotifyPropertyChanged
{
    partial void InitializePartial()
    {
        Id = Guid.NewGuid();            
    }

    public event PropertyChangedEventHandler PropertyChanged;

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

以及保存数据的方法:

public void SaveMasterData(StaffMasterData nwRowData)
{
    using (var db = CreateDbContext())
    {
        //MasterDataBinding is the observableCollection
        //the datagrid is being bound to.

        var staffNoExists = MasterDataBinding.Any(p => p.StaffNo == nwRowData.StaffNo);
        if (!staffNoExists)
        {
            db.StaffMasterDatas.AddOrUpdate(nwRowData);
            db.SaveChanges();
        }
        else
        {
            Alerts.Error("Staff Number exists");
            nwRowData.StaffNo = null;
        }
    }
}

集合改变事件的分配:

public class ShiftManagerViewModel : INotifyPropertyChanged
{
    private ObservableCollection<StaffMasterData> _mMasterDataBinding = new ObservableCollection<StaffMasterData>();

    public ObservableCollection<StaffMasterData> MasterDataBinding
    {
        get { return _mMasterDataBinding; }
        set
        {
            if (value != _mMasterDataBinding)
            {
                _mMasterDataBinding = value;
                OnPropertyChanged();                    
            }
        }
    }


    public ShiftManagerViewModel()
    {          
        _mMasterDataBinding.CollectionChanged += collectionChanged_Event;
    }


    private void collectionChanged_Event(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.NewItems != null && e.NewItems.Count > 0)
        {
            foreach (INotifyPropertyChanged item in e.NewItems.OfType<INotifyPropertyChanged>())
            {
                item.PropertyChanged += propertyChanged_Event;
            }
        }
        if (e.OldItems != null && e.OldItems.Count > 0)
        {
            foreach (INotifyPropertyChanged item in e.OldItems.OfType<INotifyPropertyChanged>())
            {
                item.PropertyChanged -= propertyChanged_Event;
            }
        }
    }

    public void propertyChanged_Event(object sender, PropertyChangedEventArgs e)
    {
        if (sender is StaffMasterData)
        {
            SaveMasterData((StaffMasterData)sender);
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

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

可能很清楚,当运行这行代码 nwRowData.StaffNo = null; 时,它会再次触发事件,因为集合已被修改,然后又运行 messageBox 代码并弹出两次。

老实说,我已经为此碰壁了,任何正确方向的观点都会受到赞赏。

【问题讨论】:

  • 为 StaffNo 属性设置支持字段,而不是设置该属性。
  • 如果你使用AddOrUpdate,为什么要检查现有的。可以使用数据库上的 StaffNo 约束来修复它并尝试/捕获它。其他进程可能会在您的支票之间写入它。
  • 在您发布的代码中,StaffNo 属性不会触发任何事件...?
  • StaffNo 如果像您发布的代码那样实现,则根本不会引发任何事件。
  • @mm8,好的,我知道发生了什么,因为这是我第一次尝试 MVVM,在我真正开始编写代码之前经过大量研究,我遇到了一个名为 @ 的 NuGet 包987654331@ 并且它使用了PropertyChanged,所以没有使用方法并且正在更新属性的原因是由于插件。对于那个很抱歉。我想我要卸载插件并使用OnPropertyChanged 方法来更好地了解正在发生的事情。我认为正在发生的事情是正常的行为。再次感谢您抽出时间提供帮助。

标签: c# wpf mvvm datagrid inotifypropertychanged


【解决方案1】:

您可以使用一个标志来确定是否实际调用SaveMasterData 方法。在将 StaffNo 属性设置为 null 之前将此标志设置为 false,然后立即将其设置回 true

private bool _handle = true;
public void SaveMasterData(StaffMasterData nwRowData)
{
    using (var db = CreateDbContext())
    {
        //MasterDataBinding is the observableCollection
        //the datagrid is being bound to.

        var staffNoExists = MasterDataBinding.Any(p => p.StaffNo == nwRowData.StaffNo);
        if (!staffNoExists)
        {
            db.StaffMasterDatas.AddOrUpdate(nwRowData);
            db.SaveChanges();
        }
        else
        {
            Alerts.Error("Staff Number exists");

            _handle = false;
            nwRowData.StaffNo = null;
            _handle = true;
        }
    }
}

public void propertyChanged_Event(object sender, PropertyChangedEventArgs e)
{
    if (!_handle && sender is StaffMasterData)
    {
        SaveMasterData((StaffMasterData)sender);
    }
}

【讨论】:

    猜你喜欢
    • 2021-04-22
    • 2016-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-06
    • 1970-01-01
    相关资源
    最近更新 更多