How to tell if user has modified data using bindingsource?

后端 未结 12 2093
南方客
南方客 2021-01-05 06:05

I have a DataGridView bound to a bindingsource which is bound to a List. The user clicks a row that goes to a form with textboxes, etc. The textboxes a

相关标签:
12条回答
  • 2021-01-05 06:36

    I set up a fairly simple mechanism, as follows:

    1. After binding my controls, I run a method that finds all the bound controls and saves their current values (I do a ReadValue() just to be sure I've got the values from the DataSource) in a Dictionary that maps a control to its value (there's a small method that gets the appropriate value for each kind of control that I have).
    2. I also add a change-event handler for each one (again, the specific event is determined by the type of control, but they all point to the same handler)
    3. The change-handler checks the current value against the Dictionary value. If it's different then it acts accordingly (in my case it switches the Close button for the Cancel button). If it's the same it checks all the other bound controls, so that if nothing is different it can switch Cancel back to Close; it's a nice feature of this method that it also recognizes when a change has been undone, even if it's by re-entering the original value.
    4. Before leaving, if there are changes to be saved I loop through the bound controls again to do WriteValue(), just in case WinForms didn't get around to propagating some change.

    I can share the source if anyone is interested.

    0 讨论(0)
  • 2021-01-05 06:42

    If your object within the List support the INotifyPropertyChanged event and you replace the List<T> by a BindingList<T> you can subscribe to the ListChanged event of the BindingList to get informed about any changes made by the user.

    0 讨论(0)
  • 2021-01-05 06:42

    After trying different thing I ended up with this piece of code:

    private MyClass currentItem = null;
    private bool itemDirty = false; // can be used for "do you want to save?"
    
    private void bindingSource_CurrentChanged(object sender, EventArgs e)
    {
        var handler = new PropertyChangedEventHandler((s, e2) => itemDirty = true);
    
        var crnt = currentItem as INotifyPropertyChanged;
        if(crnt != null) crnt.PropertyChanged -= handler;
    
        currentItem = (MyClass)bindingSource.Current;
    
        crnt = currentItem as INotifyPropertyChanged;
        if(crnt != null) crnt.PropertyChanged += handler;
    
        itemDirty = false;
    }
    

    It works fine for me, although I save lots of state information in the Windows Form's instance fields. However, twiddling with CurrentChanged and CurrentItemChanged did not help me.

    0 讨论(0)
  • 2021-01-05 06:43

    If you're bound to a DataSet then you're in luck: it has a HasChanges Property. You can get the actual changes by calling GetChanges on the dataset. This returns a new dataset containing a copy of all changed rows

    0 讨论(0)
  • 2021-01-05 06:44

    A simpler approach would be to subscribe to the BindingSource's ListChanged event and set an IsDirty flag based on the event type.

    categoryBindingSource.ListChanged += 
    new System.ComponentModel.ListChangedEventHandler(categoryBindingSource_ListChanged);
    

    and set IsDirty = true in the event method...

    void customerAccountBindingSource_ListChanged(object sender, system.ComponentModel.ListChangedEventArgs e)
    {
        if (e.ListChangedType == System.ComponentModel.ListChangedType.ItemChanged)
            _isDirty = true;
    }
    

    A word of caution here, it would not be able to detect when the modified value is still same as the original value. Memberwise.Clone can be used additionally if that level of accuracy is required.

    0 讨论(0)
  • 2021-01-05 06:44

    From my updated question I found I had to store a current version of the object at BeginEdit using Memberwise.Clone and then in CancelEdit I restored that to the current.

    0 讨论(0)
提交回复
热议问题