如何使用绑定源判断用户是否修改了数据?

发布于 2024-08-21 02:22:38 字数 464 浏览 3 评论 0原文

我有一个绑定到绑定源的 DataGridView,该绑定源绑定到 List。用户单击一行,进入带有文本框等的表单。文本框是数据绑定的,如下所示:

if (txtID.DataBindings.Count == 0)
    txtID.DataBindings.Add("Text", bindingSource, "Title");

我希望能够检测用户在单击关闭按钮时是否修改了控件中的任何数据,以便我可以提示他们会说“您有未保存的工作。要保存吗?”

如何在绑定源上检测到这一点?

更新:我已经发现我可以执行bindingSource.EndEdit(),它将更改推送到列表中的项目。在我的项目中,我可以说如果 Dirty 抛出一个消息框,但如果他们单击“否”来保存信息,则 CancelEdit 将不起作用。

I have a DataGridView bound to a bindingsource which is bound to a List<T>. The user clicks a row that goes to a form with textboxes, etc. The textboxes are databound like so:

if (txtID.DataBindings.Count == 0)
    txtID.DataBindings.Add("Text", bindingSource, "Title");

I want to be able to detect if the user has modified any data in the controls when they click the close button, so I can prompt them to say "You have un-saved work. Do you want to Save?"

How do I detect this on the binding source?

UPDATE: I have worked out that I can do bindingSource.EndEdit() which pushes the changes to my item in the list. In my item, I can then say if Dirty throw a Messagebox but if they click "No" to saving the information, the CancelEdit does not work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

如梦初醒的夏天 2024-08-28 02:22:38

如果列表中的对象支持 INotifyPropertyChanged 事件,并将 List 替换为 BindingList您可以订阅 ListChanged 事件,用于获取用户所做的任何更改的通知。

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.

帅冕 2024-08-28 02:22:38

如果您绑定到 DataSet 那么您很幸运:它有一个 HasChanges 属性。您可以通过对数据集调用 GetChanges 来获取实际更改。这将返回一个新数据集,其中包含所有更改行的副本

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

终止放荡 2024-08-28 02:22:38

我现在做了这个功能。你可以这样使用:

if (changedOrNew(myBindingSource)){
    // Do something!
}

public bool changedOrNew(BindingSource bs){
    EntityObject obj = (EntityObject)bs.Current;
    if (obj==null)
        return false;
    return (obj.EntityState == EntityState.Detached ||
            obj.EntityState == EntityState.Added ||
            obj.EntityState == EntityState.Modified);
}

I made this function now. You can use like:

if (changedOrNew(myBindingSource)){
    // Do something!
}

public bool changedOrNew(BindingSource bs){
    EntityObject obj = (EntityObject)bs.Current;
    if (obj==null)
        return false;
    return (obj.EntityState == EntityState.Detached ||
            obj.EntityState == EntityState.Added ||
            obj.EntityState == EntityState.Modified);
}
寂寞花火° 2024-08-28 02:22:38

在尝试了不同的事情之后,我最终得到了这段代码:

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;
}

尽管我在 Windows 窗体的实例字段中保存了大量状态信息,但它对我来说工作得很好。但是,使用 CurrentChangedCurrentItemChanged 并没有帮助我。

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.

吹梦到西洲 2024-08-28 02:22:38

一种更简单的方法是订阅 BindingSource 的 ListChanged 事件并根据事件类型设置 IsDirty 标志。

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

并在事件方法中设置 IsDirty = true...

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

这里需要注意的是,它无法检测修改后的值何时仍与原始值相同。如果需要该级别的准确性,可以另外使用 Memberwise.Clone

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.

我的黑色迷你裙 2024-08-28 02:22:38

我设置了一个相当简单的机制,如下所示:

  1. 绑定控件后,我运行一个方法来查找所有绑定的
    控制并保存它们的当前值(我执行ReadValue()只是为了
    确保我已从字典中的数据源获取值
    将控件映射到其值(有一个小方法可以获取
    我拥有的每种控件的适当值)。
  2. 我还为每个事件添加了一个更改事件处理程序(同样,具体的
    事件由控件类型决定,但它们都指向
    相同的处理程序)
  3. 更改处理程序根据字典检查当前值
    价值。如果不同,那么它会相应地采取行动(在我的例子中
    关闭按钮切换为取消按钮)。如果是一样的话
    它检查所有其他绑定控件,以便如果没有
    不同的是可以将取消切换回关闭;这是一个很好的功能
    当更改被撤消时它也可以识别这种方法,
    即使是通过重新输入原始值。
  4. 在离开之前,如果有需要保存的更改,我会循环遍历
    再次绑定控件以执行 WriteValue(),以防万一 WinForms 没有执行
    抽出时间去传播一些改变。

如果有人感兴趣,我可以分享来源。

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.

流年已逝 2024-08-28 02:22:38

如果您的绑定源使用数据表,您可以这样做:

    public bool HasChanges()
    {
        bool Result = false;

        myBindingSource.EndEdit();
        Result = ((DataTable)myBindingSource.DataSource).GetChanges(DataRowState.Modified) != null;


        return Result;
    }

If your bindingsource uses a datatable you can do this :

    public bool HasChanges()
    {
        bool Result = false;

        myBindingSource.EndEdit();
        Result = ((DataTable)myBindingSource.DataSource).GetChanges(DataRowState.Modified) != null;


        return Result;
    }
∞觅青森が 2024-08-28 02:22:38

我知道这是一篇旧文章,但这里有一个带有 IsDirtyFlag 的扩展 BindingSource - 您可以按照自己的意愿调整它 - 我几年前从网络上的另一个帖子中提取了此代码 - 做了一些非常小的更改,我认为它最初是在VB - 我转换为 C# ..

using System.ComponentModel.Design;
using System.Windows.Forms;
using System.ComponentModel;
using System.Data;
using System;


public class BindingSourceExIsDirty : System.Windows.Forms.BindingSource, INotifyPropertyChanged
{

    #region "DECLARATIONS AND PROPERTIES"

    private string _displayMember;
    private DataTable _dataTable;
    private DataSet _dataSet;
    private BindingSource _parentBindingSource;
    private System.Windows.Forms.Form _form;
    private System.Windows.Forms.Control _usercontrol;




    private bool _isCurrentDirtyFlag = false;
    public bool IsCurrentDirty {
        get { return _isCurrentDirtyFlag; }
        set {
            if (_isCurrentDirtyFlag != value) {
                _isCurrentDirtyFlag = value;
                this.OnPropertyChanged(value.ToString());
                //call the event when flag is set
                if (value == true) {
                    OnCurrentIsDirty(new EventArgs());

                }
            }
        }
    }


    private string _objectSource;
    public string ObjectSource {
        get { return _objectSource; }
        set {
            _objectSource = value;
            this.OnPropertyChanged(value);
        }
    }


private bool _autoSaveFlag;

public bool AutoSave {
    get { return _autoSaveFlag; }
    set {
        _autoSaveFlag = value;
        this.OnPropertyChanged(value.ToString());
    }
} 

    #endregion

    #region "EVENTS"


    //Current Is Dirty Event
    public event CurrentIsDirtyEventHandler CurrentIsDirty;

    // Delegate declaration.
    public delegate void CurrentIsDirtyEventHandler(object sender, EventArgs e);

    protected virtual void OnCurrentIsDirty(EventArgs e)
    {
        if (CurrentIsDirty != null) {
            CurrentIsDirty(this, e);
        }
    }

    //PropertyChanged Event 
//  public event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged;

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string info)
    {

        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(info));
        }       

    }



    #endregion

    #region "METHODS"



    private void _BindingComplete(System.Object sender, System.Windows.Forms.BindingCompleteEventArgs e)
    {

        if (e.BindingCompleteContext == BindingCompleteContext.DataSourceUpdate) {

            if (e.BindingCompleteState == BindingCompleteState.Success & !e.Binding.Control.BindingContext.IsReadOnly) {
                //Make sure the data source value is refreshed (fixes problem mousing off control)
                e.Binding.ReadValue();
                //if not focused then not a user edit.
                if (!e.Binding.Control.Focused)
                    return;

                //check for the lookup type of combobox that changes position instead of value
                if (e.Binding.Control as ComboBox != null) {
                    //if the combo box has the same data member table as the binding source, ignore it
                    if (((ComboBox)e.Binding.Control).DataSource != null) {
                        if (((ComboBox)e.Binding.Control).DataSource as BindingSource != null) {
                            if (((BindingSource)((ComboBox)e.Binding.Control).DataSource).DataMember == (this.DataMember)) {
                                return;
                            }

                        }

                    }
                }
                IsCurrentDirty = true;
                //set the dirty flag because data was changed
            }
        }



    }

    private void _DataSourceChanged(System.Object sender, System.EventArgs e)
    {
        _parentBindingSource = null;
        if (this.DataSource == null) {
            _dataSet = null;
        } else {
            //get a reference to the dataset
            BindingSource bsTest = this;
            Type dsType = bsTest.DataSource.GetType();
            //try to cast the data source as a binding source
            while ((bsTest.DataSource as BindingSource != null)) {
                //set the parent binding source reference
                if (_parentBindingSource == null)
                    _parentBindingSource = bsTest;
                //if cast was successful, walk up the chain until dataset is reached
                bsTest = (BindingSource)bsTest.DataSource;
            }
            //since it is no longer a binding source, it must be a dataset or something else
            if (bsTest.DataSource as DataSet == null) {
                //Cast as dataset did not work

                if (dsType.IsClass == false) {
                    throw new ApplicationException("Invalid Binding Source ");
                } else {
                    _dataSet = null;

                }

            } else {
                _dataSet = (DataSet)bsTest.DataSource;
            }


            //is there a data member - find the datatable
            if (!string.IsNullOrEmpty(this.DataMember)) {
                _DataMemberChanged(sender, e);
            }
            //CType(value.GetService(GetType(IDesignerHost)), IDesignerHost)
            if (_form == null)
                GetFormInstance();
            if (_usercontrol == null)
                GetUserControlInstance();
        }
    }

    private void _DataMemberChanged(System.Object sender, System.EventArgs e)
    {
        if (string.IsNullOrEmpty(this.DataMember) | _dataSet == null) {
            _dataTable = null;
        } else {
            //check to see if the Data Member is the name of a table in the dataset
            if (_dataSet.Tables(this.DataMember) == null) {
                //it must be a relationship instead of a table
                System.Data.DataRelation rel = _dataSet.Relations(this.DataMember);
                if ((rel != null)) {
                    _dataTable = rel.ChildTable;
                } else {
                    throw new ApplicationException("Invalid Data Member");
                }
            } else {
                _dataTable = _dataSet.Tables(this.DataMember);
            }
        }
    }

    public override System.ComponentModel.ISite Site {
        get { return base.Site; }
        set {
            //runs at design time to initiate ContainerControl
            base.Site = value;
            if (value == null)
                return;
            // Requests an IDesignerHost service using Component.Site.GetService()
            IDesignerHost service = (IDesignerHost)value.GetService(typeof(IDesignerHost));
            if (service == null)
                return;
            if ((service.RootComponent as Form != null)) {
                _form = (Form)service.RootComponent;
            } else if ((service.RootComponent as UserControl != null)) {
                _usercontrol = (UserControl)service.RootComponent;
            }

        }
    }

    public System.Windows.Forms.Form GetFormInstance()
    {
        if (_form == null & this.CurrencyManager.Bindings.Count > 0) {
            _form = this.CurrencyManager.Bindings[0].Control.FindForm();

        }
        return _form;
    }

    /// <summary>
    /// Returns the First Instance of the specified User Control
    /// </summary>
    /// <returns>System.Windows.Forms.Control</returns>
    public System.Windows.Forms.Control GetUserControlInstance()
    {
        if (_usercontrol == null & this.CurrencyManager.Bindings.Count > 0) {
            System.Windows.Forms.Control[] _uControls = null;
            _uControls = this.CurrencyManager.Bindings[0].Control.FindForm().Controls.Find(this.Site.Name.ToString(), true);
            _usercontrol = _uControls[0];

        }
        return _usercontrol;
    }
    public BindingSourceExIsDirty()
    {
        DataMemberChanged += _DataMemberChanged;
        DataSourceChanged += _DataSourceChanged;
        BindingComplete += _BindingComplete;
    }

// PositionChanged
private override void _PositionChanged(object sender, EventArgs e)
{
    if (IsCurrentDirty) {
        // IsAutoSavingEvent
        if (AutoSave | MessageBox.Show(_msg, "Confirm Save", MessageBoxButtons.YesNo) == DialogResult.Yes) {
            try {
                //cast table as ITableUpdate to get the Update method
                //  CType(_dataTable, ITableUpdate).Update()
            } catch (Exception ex) {
                MessageBox.Show(ex, "Position Changed Error");
                // - needs to raise an event 
            }
        } else {
            this.CancelEdit();
            _dataTable.RejectChanges();
        }
        IsCurrentDirty = false;

    }
 base(e);
}


    #endregion

}

I know this is an old post but here is an Extended BindingSource with IsDirtyFlag - you can adapt it how you would like - I pulled this code from another posting somewhere on the net years ago - made some very minor changes I think it was originally in VB - I converted to C# ..

using System.ComponentModel.Design;
using System.Windows.Forms;
using System.ComponentModel;
using System.Data;
using System;


public class BindingSourceExIsDirty : System.Windows.Forms.BindingSource, INotifyPropertyChanged
{

    #region "DECLARATIONS AND PROPERTIES"

    private string _displayMember;
    private DataTable _dataTable;
    private DataSet _dataSet;
    private BindingSource _parentBindingSource;
    private System.Windows.Forms.Form _form;
    private System.Windows.Forms.Control _usercontrol;




    private bool _isCurrentDirtyFlag = false;
    public bool IsCurrentDirty {
        get { return _isCurrentDirtyFlag; }
        set {
            if (_isCurrentDirtyFlag != value) {
                _isCurrentDirtyFlag = value;
                this.OnPropertyChanged(value.ToString());
                //call the event when flag is set
                if (value == true) {
                    OnCurrentIsDirty(new EventArgs());

                }
            }
        }
    }


    private string _objectSource;
    public string ObjectSource {
        get { return _objectSource; }
        set {
            _objectSource = value;
            this.OnPropertyChanged(value);
        }
    }


private bool _autoSaveFlag;

public bool AutoSave {
    get { return _autoSaveFlag; }
    set {
        _autoSaveFlag = value;
        this.OnPropertyChanged(value.ToString());
    }
} 

    #endregion

    #region "EVENTS"


    //Current Is Dirty Event
    public event CurrentIsDirtyEventHandler CurrentIsDirty;

    // Delegate declaration.
    public delegate void CurrentIsDirtyEventHandler(object sender, EventArgs e);

    protected virtual void OnCurrentIsDirty(EventArgs e)
    {
        if (CurrentIsDirty != null) {
            CurrentIsDirty(this, e);
        }
    }

    //PropertyChanged Event 
//  public event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged;

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string info)
    {

        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(info));
        }       

    }



    #endregion

    #region "METHODS"



    private void _BindingComplete(System.Object sender, System.Windows.Forms.BindingCompleteEventArgs e)
    {

        if (e.BindingCompleteContext == BindingCompleteContext.DataSourceUpdate) {

            if (e.BindingCompleteState == BindingCompleteState.Success & !e.Binding.Control.BindingContext.IsReadOnly) {
                //Make sure the data source value is refreshed (fixes problem mousing off control)
                e.Binding.ReadValue();
                //if not focused then not a user edit.
                if (!e.Binding.Control.Focused)
                    return;

                //check for the lookup type of combobox that changes position instead of value
                if (e.Binding.Control as ComboBox != null) {
                    //if the combo box has the same data member table as the binding source, ignore it
                    if (((ComboBox)e.Binding.Control).DataSource != null) {
                        if (((ComboBox)e.Binding.Control).DataSource as BindingSource != null) {
                            if (((BindingSource)((ComboBox)e.Binding.Control).DataSource).DataMember == (this.DataMember)) {
                                return;
                            }

                        }

                    }
                }
                IsCurrentDirty = true;
                //set the dirty flag because data was changed
            }
        }



    }

    private void _DataSourceChanged(System.Object sender, System.EventArgs e)
    {
        _parentBindingSource = null;
        if (this.DataSource == null) {
            _dataSet = null;
        } else {
            //get a reference to the dataset
            BindingSource bsTest = this;
            Type dsType = bsTest.DataSource.GetType();
            //try to cast the data source as a binding source
            while ((bsTest.DataSource as BindingSource != null)) {
                //set the parent binding source reference
                if (_parentBindingSource == null)
                    _parentBindingSource = bsTest;
                //if cast was successful, walk up the chain until dataset is reached
                bsTest = (BindingSource)bsTest.DataSource;
            }
            //since it is no longer a binding source, it must be a dataset or something else
            if (bsTest.DataSource as DataSet == null) {
                //Cast as dataset did not work

                if (dsType.IsClass == false) {
                    throw new ApplicationException("Invalid Binding Source ");
                } else {
                    _dataSet = null;

                }

            } else {
                _dataSet = (DataSet)bsTest.DataSource;
            }


            //is there a data member - find the datatable
            if (!string.IsNullOrEmpty(this.DataMember)) {
                _DataMemberChanged(sender, e);
            }
            //CType(value.GetService(GetType(IDesignerHost)), IDesignerHost)
            if (_form == null)
                GetFormInstance();
            if (_usercontrol == null)
                GetUserControlInstance();
        }
    }

    private void _DataMemberChanged(System.Object sender, System.EventArgs e)
    {
        if (string.IsNullOrEmpty(this.DataMember) | _dataSet == null) {
            _dataTable = null;
        } else {
            //check to see if the Data Member is the name of a table in the dataset
            if (_dataSet.Tables(this.DataMember) == null) {
                //it must be a relationship instead of a table
                System.Data.DataRelation rel = _dataSet.Relations(this.DataMember);
                if ((rel != null)) {
                    _dataTable = rel.ChildTable;
                } else {
                    throw new ApplicationException("Invalid Data Member");
                }
            } else {
                _dataTable = _dataSet.Tables(this.DataMember);
            }
        }
    }

    public override System.ComponentModel.ISite Site {
        get { return base.Site; }
        set {
            //runs at design time to initiate ContainerControl
            base.Site = value;
            if (value == null)
                return;
            // Requests an IDesignerHost service using Component.Site.GetService()
            IDesignerHost service = (IDesignerHost)value.GetService(typeof(IDesignerHost));
            if (service == null)
                return;
            if ((service.RootComponent as Form != null)) {
                _form = (Form)service.RootComponent;
            } else if ((service.RootComponent as UserControl != null)) {
                _usercontrol = (UserControl)service.RootComponent;
            }

        }
    }

    public System.Windows.Forms.Form GetFormInstance()
    {
        if (_form == null & this.CurrencyManager.Bindings.Count > 0) {
            _form = this.CurrencyManager.Bindings[0].Control.FindForm();

        }
        return _form;
    }

    /// <summary>
    /// Returns the First Instance of the specified User Control
    /// </summary>
    /// <returns>System.Windows.Forms.Control</returns>
    public System.Windows.Forms.Control GetUserControlInstance()
    {
        if (_usercontrol == null & this.CurrencyManager.Bindings.Count > 0) {
            System.Windows.Forms.Control[] _uControls = null;
            _uControls = this.CurrencyManager.Bindings[0].Control.FindForm().Controls.Find(this.Site.Name.ToString(), true);
            _usercontrol = _uControls[0];

        }
        return _usercontrol;
    }
    public BindingSourceExIsDirty()
    {
        DataMemberChanged += _DataMemberChanged;
        DataSourceChanged += _DataSourceChanged;
        BindingComplete += _BindingComplete;
    }

// PositionChanged
private override void _PositionChanged(object sender, EventArgs e)
{
    if (IsCurrentDirty) {
        // IsAutoSavingEvent
        if (AutoSave | MessageBox.Show(_msg, "Confirm Save", MessageBoxButtons.YesNo) == DialogResult.Yes) {
            try {
                //cast table as ITableUpdate to get the Update method
                //  CType(_dataTable, ITableUpdate).Update()
            } catch (Exception ex) {
                MessageBox.Show(ex, "Position Changed Error");
                // - needs to raise an event 
            }
        } else {
            this.CancelEdit();
            _dataTable.RejectChanges();
        }
        IsCurrentDirty = false;

    }
 base(e);
}


    #endregion

}
梦里梦着梦中梦 2024-08-28 02:22:38

从我更新的问题中,我发现我必须使用 Memberwise.Clone 在 BeginEdit 中存储对象的当前版本,然后在 CancelEdit 中将其恢复到当前版本。

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.

无声无音无过去 2024-08-28 02:22:38

我总是做的是捕获控件的各个“更改”事件。在下面的示例中,我在本示例中使用了选项卡控件。 Try/Catch 是一个肮脏的解决方案,因为不必处理各种异常;-)

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    '
    ' some code        
    '
    BindingNavigatorSaveItem.Enabled = False
    For Each tabctl As Control In Me.TabControl1.Controls
        For Each ctl As Control In tabctl.Controls
            Try
                If ctl.GetType Is GetType(TextBox) Then
                    AddHandler DirectCast(ctl, TextBox).TextChanged, AddressOf GenDataChanged
                ElseIf ctl.GetType Is GetType(NumericUpDown) Then
                    AddHandler DirectCast(ctl, NumericUpDown).ValueChanged, AddressOf GenDataChanged
                ElseIf ctl.GetType Is GetType(ComboBox) Then
                    AddHandler DirectCast(ctl, ComboBox).SelectedValueChanged, AddressOf GenDataChanged
                ElseIf ctl.GetType Is GetType(CheckBox) Then
                    AddHandler DirectCast(ctl, CheckBox).CheckStateChanged, AddressOf GenDataChanged
                End If
            Catch ex As Exception
            End Try
        Next
    Next
End Sub

Private Sub GenDataChanged(sender As System.Object, e As System.EventArgs)
    BindingNavigatorSaveItem.Enabled = True
End Sub

What I always do is to capture the individual "changed" events of the controls. In the below example I used a tabcontrol in this example. The Try/Catch is a dirty solution for not having to deal with all kinds of exceptions ;-)

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    '
    ' some code        
    '
    BindingNavigatorSaveItem.Enabled = False
    For Each tabctl As Control In Me.TabControl1.Controls
        For Each ctl As Control In tabctl.Controls
            Try
                If ctl.GetType Is GetType(TextBox) Then
                    AddHandler DirectCast(ctl, TextBox).TextChanged, AddressOf GenDataChanged
                ElseIf ctl.GetType Is GetType(NumericUpDown) Then
                    AddHandler DirectCast(ctl, NumericUpDown).ValueChanged, AddressOf GenDataChanged
                ElseIf ctl.GetType Is GetType(ComboBox) Then
                    AddHandler DirectCast(ctl, ComboBox).SelectedValueChanged, AddressOf GenDataChanged
                ElseIf ctl.GetType Is GetType(CheckBox) Then
                    AddHandler DirectCast(ctl, CheckBox).CheckStateChanged, AddressOf GenDataChanged
                End If
            Catch ex As Exception
            End Try
        Next
    Next
End Sub

Private Sub GenDataChanged(sender As System.Object, e As System.EventArgs)
    BindingNavigatorSaveItem.Enabled = True
End Sub
一瞬间的火花 2024-08-28 02:22:38

我不确定在提出问题时它是否可用,但我使用 grid_CurrentCellDirtyStateChanged;事件

I aren't sure if it was available when the question was asked but I use the grid_CurrentCellDirtyStateChanged; event

追风人 2024-08-28 02:22:38

首先确保您设置了 DataSourceUpdateMode.OnPropertyChanged

txrFirstName.DataBindings.Add("Text", bindingSource1, "FirstName", false,DataSourceUpdateMode.OnPropertyChanged);

然后添加将此代码添加到您的 movenext 点击事件中

 if (((DataRowView)bindingSource1.Current).IsNew)
                {
                MessageBox.Show("Current Row IsNew");
                }
            if (((DataRowView)bindingSource1.CurrencyManager.Current).Row.HasVersion(DataRowVersion.Proposed))
                {
                MessageBox.Show("Current Row Modified");
                DialogResult dialogResult = MessageBox.Show("Current Row Modified", "Some Title", MessageBoxButtons.YesNo);
                if (dialogResult == DialogResult.Yes)
                    {
                    //do something
                    ((DataRowView)bindingSource1.CurrencyManager.Current).Row.AcceptChanges();
                    }
                else if (dialogResult == DialogResult.No)
                    {
                    //do something else
                    ((DataRowView)bindingSource1.CurrencyManager.Current).Row.RejectChanges();
                    }


                }
            else { 
                bindingSource1.MoveNext();
                }

first make Sure you set DataSourceUpdateMode.OnPropertyChanged

txrFirstName.DataBindings.Add("Text", bindingSource1, "FirstName", false,DataSourceUpdateMode.OnPropertyChanged);

then add add this code to your movenext click event

 if (((DataRowView)bindingSource1.Current).IsNew)
                {
                MessageBox.Show("Current Row IsNew");
                }
            if (((DataRowView)bindingSource1.CurrencyManager.Current).Row.HasVersion(DataRowVersion.Proposed))
                {
                MessageBox.Show("Current Row Modified");
                DialogResult dialogResult = MessageBox.Show("Current Row Modified", "Some Title", MessageBoxButtons.YesNo);
                if (dialogResult == DialogResult.Yes)
                    {
                    //do something
                    ((DataRowView)bindingSource1.CurrencyManager.Current).Row.AcceptChanges();
                    }
                else if (dialogResult == DialogResult.No)
                    {
                    //do something else
                    ((DataRowView)bindingSource1.CurrencyManager.Current).Row.RejectChanges();
                    }


                }
            else { 
                bindingSource1.MoveNext();
                }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文