是否可以取消在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中也会出现一个新的(“空”)项。
是否可以取消添加项目?
答案 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)
一个简单的解决方案:
双击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;
}