【问题标题】:BindingSource cancel AddingNewBindingSource 取消添加新
【发布时间】:2023-03-31 23:22:01
【问题描述】:

是否可以取消在BindingSource.AddingNew 事件处理程序中添加项目?

当用户单击我的BindingNavigator 中的“添加新”按钮时,我正在打开一个对话框,该对话框可能会或可能不会返回有效文件。现在,我有这样的事情:

void bindingSource_AddingNew(object sender, AddingNewEventArgs e)
{
    using (var dialog = new OpenFileDialog())
    {
        var result = dialog.ShowDialog();

        // user canceled?
        if (result == DialogResult.Cancel)
            return;

        // TryLoad will return null on failure
        var data = TryLoad(dialog.FileName);

        // only add the item to the grid if not null
        if (data != null)
            e.NewObject = data;
    }
}

即使我没有将e.NewObject 设置为处理程序内的值,DataGridView 中也会出现一个新的(“空”)项。

是否可以取消添加项目?

【问题讨论】:

  • 如果你没有设置e.NewObject,它会为你创建一个。

标签: c# .net datagridview bindingsource


【解决方案1】:

如果您的 BindingSource 实现了ICancelAddNew 接口,您应该能够在新添加的对象上调用 CancelNew 来恢复它。我不建议在 AddNew 的事件处理程序中尝试此操作。通过使用此接口,您的项目仍将添加到列表中,但处于挂起状态,其中 EndNew() 将提交事务,而 CancelNew() 将恢复事务。看起来 BindingList 实现了 ICancelNew 并允许您执行以下操作:

public void MyFunctionWhereIAddNew()
{
    var item  = _myBindingSource.AddNew();

    item.SetSomeParams(...);

    if(item.CheckItemForSuccess() != true)
    {
        _myBindingSource.CancelNew(_myBindingSource.IndexOf(item));
    }
}

如果您想获得有关如何实施自己的 ICancelNew 的链接,请查看 this old blog post

【讨论】:

  • 谢谢。但是,如果我通过BindingNavigator 添加行(我没有从代码中调用AddNew),我只会触发AddingNew 事件。
  • 如何为AddingNew 事件添加事件监听器?如何为 BindingNavigator 创建 BindingSource?
  • 我使用列表作为 BindingSource 的数据源:List<T> list = GetData(); bindingSource.DataSource = list;,我使用 BindingSource 作为网格和导航器的数据源:dataGridView.DataDource = bindingSource; bindingNavigator.DataSource = bindingSource;。这为我提供了开箱即用的网格 + 导航器功能,但是一旦用户点击 BindingNavigator 控件上的“添加”按钮,就无法取消添加。
【解决方案2】:

一个简单的解决方案:

  1. 清除“属性”窗口中的 BindingNavigator“AddNewItem”属性,这样它就不会触发 bindingsourceAddingNew。
  2. 在bindingNavigator中双击加号,为加号按钮生成Click事件,手动控制添加新项的过程,如下:

    private void bindingNavigatorAddNewItem_Click(object sender, EventArgs e)
    {
        using (var dialog = new OpenFileDialog())
        {
            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                var data = TryLoad(dialog.FileName); ;
    
                if (data != null)
                {
                    myBindingSource.Add(data);
                }
            }
        }
    }
    

【讨论】:

  • 谢谢,这就是我想要的。简单,没有反射,做的就是预期的。我不知道这些属性存在。太好了!
【解决方案3】:

这是可能的,但以一种非常丑陋的方式。您必须覆盖BindingNavigator 的添加按钮的单击事件。下面提供的解决方案测试和工作,但显然不适合任何生产系统。我在生产系统中有一个这样的代码来重新排序事件处理程序。我不喜欢它,但它有效。

public partial class Form1 : Form
{
    public MethodInfo refreshMethod;
    public Form1()
    {
        InitializeComponent();

        // Build Data
        var list = new List<MyData>
            {
                new MyData {Id = 1, Str = "1"},
                new MyData {Id = 2, Str = "2"}
            };

        //Bind Data
        bindingSource1.DataSource = list;
        dataGridView1.DataSource = bindingSource1;
        bindingNavigator1.BindingSource = bindingSource1;

        // get event handler storage property
        var eventsProperty = bindingNavigator1.AddNewItem.GetType().GetProperty(
            "Events",
            BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Instance
            );

        // get key for click event
        var clickField = bindingNavigator1.AddNewItem.GetType().GetField(
            "EventClick",
            BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Static
            );

        var clickKey = clickField.GetValue(null);

        // find refresh method
        refreshMethod = bindingNavigator1.GetType().GetMethod(
            "RefreshItemsInternal",
            BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.Instance
            );

        // get storage instance
        var handlers = (EventHandlerList)eventsProperty.GetValue(bindingNavigator1.AddNewItem, null);
        // find click event handlers
        var clickEventHandlers = handlers[clickKey];

        // remove current handlers
        var handlerInvocationList = clickEventHandlers.GetInvocationList();
        for (int index = 0; index < handlerInvocationList.Length; index++)
            handlers.RemoveHandler(clickKey, handlerInvocationList[index]);

        // attach our new handler
        handlers.AddHandler(clickKey, new EventHandler(NewAddNewHandler));
    }

    private void NewAddNewHandler(object sender, EventArgs e)
    {
        if (bindingNavigator1.Validate() && null != bindingNavigator1.BindingSource)
        {
            var result = MessageBox.Show("Add new?", "Are you..", MessageBoxButtons.YesNo) == DialogResult.Yes;

            if (!result)
                return;

            bindingNavigator1.BindingSource.AddNew();
            refreshMethod.Invoke(bindingNavigator1, null);
        }
    }

}

【讨论】:

    【解决方案4】:

    一个简单的解决方案是取消绑定导航器中的编辑AddNew点击事件。

    您确实需要在 bindingSource_AddingNew(..) 中设置一个布尔值,以指示您是否要取消编辑。

    private void bindingNavigatorAddNewItem_Click(object sender, EventArgs e) { 如果(取消编辑) bindingSource.CancelEdit(); }

    【讨论】:

      【解决方案5】:

      你能用按钮处理添加吗?如果是这样,您可以在调用 DataGridView 的 Add 方法之前设置按钮单击事件以检查所有参数。

      【讨论】:

        【解决方案6】:

        如果您要显示一个对话框,用于从某个数据源的表中添加或编辑数据,您可以在需要取消添加新行的任何时候简单地使用BindingSource.CancelEdit() 函数并使用BindingSource.EndEdit() 接受并结束编辑有效上传到数据库的输入数据,例如在添加/编辑对话框表单中使用这些代码行(其文本框绑定到contactsBindingSource):

        Private Sub btnOK_Click(sender As Object, e As EventArgs) Handles btnOK.Click
            contactsBindingSource.EndEdit()
            contactsTableAdapter.Update(contactsTable)
            contactsTable = contactsTableAdapter.GetData()
        End Sub
        
        Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click
            contactsBindingSource.CancelEdit()
            contactsTable = contactsTableAdapter.GetData()
        End Sub
        

        【讨论】:

          【解决方案7】:

          我的建议是重写从 BindingSource 继承的类中的 AddNew 方法。

          public override object AddNew() {
          {
            if (CreateNewItem( out newItem))
            {
              base.Add(newItem);
              return newItem;
            }
            return null;
          }
          

          【讨论】:

            猜你喜欢
            • 2016-08-02
            • 2010-12-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-06-16
            • 1970-01-01
            相关资源
            最近更新 更多