我有一个绑定到绑定列表的DevExpress GridView控件。我试图模拟SQL Server Management Studio,如果删除一行并且由于约束而失败,则该行仍保留在网格中。我通过使用BindingList的子类来处理这个问题,该子类重写了RemoveAt并告诉对象在调用base.RemoveAt之前从数据库中删除自己。但是,这似乎会导致崩溃应用程序的异常。我还没有从网格中找到任何事件来处理错误以防止这种情况发生。这是代码:
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Windows.Forms;
namespace DXGridRemoveItem {
static class Program {
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
public sealed class CustomBindingList : BindingList<BusinessObject> {
public CustomBindingList() {
AllowEdit = true;
AllowRemove = true;
AllowNew = true;
}
protected override void RemoveItem(int index) {
var item = this[index];
item.Save();
base.RemoveItem(index);
}
}
[Serializable]
public sealed class ObjectInUseException : Exception {
public ObjectInUseException() { }
public ObjectInUseException(string message) : base(message) { }
public ObjectInUseException(string message, Exception innerException) : base(message, innerException) { }
private ObjectInUseException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
public sealed class BusinessObject : IEditableObject, INotifyPropertyChanged {
private static int nextId;
private DataStorage currentData;
private DataStorage savedData;
private bool editing;
public BusinessObject() {
currentData = new DataStorage(nextId++);
}
public int Id => currentData.Id;
public string Name {
get => currentData.Name;
set {
if (currentData.Name != value) {
currentData.Name = value;
OnPropertyChanged(nameof(Name));
}
}
}
public void Save() {
if (editing) { throw new InvalidOperationException("Cannot save object while it is being edited."); }
// This happens because we tried to remove a row and a SQL constraint is preventing it
throw new ObjectInUseException();
}
public void BeginEdit() {
if (!editing) {
editing = true;
savedData = currentData;
}
}
public void EndEdit() {
if (editing) {
savedData = null;
editing = false;
}
}
public void CancelEdit() {
if (editing) {
currentData = savedData;
editing = false;
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "") {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private class DataStorage {
public DataStorage(int id) {
Id = id;
}
public int Id { get; set; }
public string Name { get; set; }
}
}
}
Form1的代码;带有删除按钮的ToolStrip
,添加了DX GridControl
,并添加了BindingSource
。 BindingSource
DataSource
为CustomBindingList
,网格DataSource
为BindingSource
。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace DXGridRemoveItem {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
protected override void OnShown(EventArgs e) {
var list = new CustomBindingList {
new BusinessObject {Name = "Name 1"},
new BusinessObject {Name = "Name 2"},
new BusinessObject {Name = "Name 3"},
new BusinessObject {Name = "Name 4"}
};
bindingSource1.DataSource = list;
base.OnShown(e);
}
private void toolStripButton1_Click(object sender, EventArgs e) {
gridView1.DeleteSelectedRows();
}
}
}