2

是否可以取消在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 中也会出现一个新的(“空”)项。

是否可以取消添加项目?

4

7 回答 7

5

如果您的 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 的链接,请查看此旧博客文章

于 2012-10-02T13:25:52.163 回答
3

一个简单的解决方案:

  1. 清除“属性”窗口中的 BindingNavigator“AddNewItem”属性,使其不会触发 bindingsource AddNewItem。
  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);
                }
            }
        }
    }
    
于 2012-10-08T21:15:18.923 回答
2

一个简单的解决方案在我将它变成任何类似产品之前肯定需要添加一些内容是取消绑定导航器AddNew点击事件中的编辑。

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

     
private void bindingNavigatorAddNewItem_Click(object sender, EventArgs e)
{       
    如果(取消编辑)
        bindingSource.CancelEdit();
}
于 2012-10-09T11:13:16.050 回答
2

这是可能的,但以一种非常丑陋的方式。您必须覆盖的添加按钮的单击事件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);
        }
    }

}
于 2012-10-05T09:12:26.937 回答
1

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

于 2012-10-08T15:20:40.813 回答
0

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

public override object AddNew() {
{
  if (CreateNewItem( out newItem))
  {
    base.Add(newItem);
    return newItem;
  }
  return null;
}
于 2020-08-25T11:14:12.860 回答
0

如果您正在显示一个对话框表单,用于从某个数据源的表中添加或编辑数据,您可以随时简单地使用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
于 2015-10-28T13:35:00.010 回答