BindingSource取消AddingNew

时间:2012-09-24 13:19:29

标签: c# .net datagridview bindingsource

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

是否可以取消添加项目?

7 个答案:

答案 0 :(得分:4)

如果您的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

答案 1 :(得分:3)

一个简单的解决方案:

  1. 清除属性窗口中的BindingNavigator“AddNewItem”属性,以便它不会触发bindingsource AddingNew。
  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);
                }
            }
        }
    }
    

答案 2 :(得分: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);
        }
    }

}

答案 3 :(得分:2)

一个简单的解决方案肯定需要一些补充才能使其成为生产类似的东西,取消绑定导航器 AddNew 点击事件中的编辑。

您需要在bindingSource_AddingNew(..)中设置一个布尔值,指示取消编辑是否是您想要执行的操作。

     
private void bindingNavigatorAddNewItem_Click(object sender, EventArgs e)
{       
    if(cancelEdit)
        bindingSource.CancelEdit();
}

答案 4 :(得分:1)

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

答案 5 :(得分: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

答案 6 :(得分:0)

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

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