网格从列表中删除对象时处理异常?

时间:2017-11-14 16:28:29

标签: winforms data-binding devexpress bindinglist

我有一个绑定到绑定列表的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,并添加了BindingSourceBindingSource DataSourceCustomBindingList,网格DataSourceBindingSource

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();
        }
    }
}

0 个答案:

没有答案