创建可以绑定到DataGrid自定义集合(Creating a custom collection

2019-09-19 06:11发布

我工作的一个建筑公司工作,我创建一个3D建模程序,以协助设计一个插件。 我有一个建筑类和底盘类。 该建筑包含了地板的FloorList集合的引用。 我想弄清楚如何立足FloorList收集掉,这样我可以最大限度地减少工作,我需要做的创建编辑采集接口的数量。

地板集合表示一系列堆叠在彼此顶部的建筑楼层。 每个楼层都有被读写一个Floor.Height财产,而且是只读的,由共计当前的地板下方的地面高度设置Floor.Elevation属性。 所以,每当中添加,删除,移动或改变了集合Floor.Elevation性能需要更新英寸

另外,我想创建一个用户界面编辑该集合。 我想用每个列出了它的高度和其他属性控制的排DataGrid控件的。 用户应该能够添加,删除,并重新使用的控制命令地板。 我想这一设置是一样方便,灵活越好。 这意味着我想简单地能够结合地面到DataGrid的收集和具有基于地板类的属性DataGrid中填入的列。 如果可能的话我希望能够利用内置在添加/删除具有惹了我的采集和数据网格之间建立一串事件关系的DataGrid控件的UI界面。

要的东西在未来的进一步复杂化,我需要能够允许用户动态地添加自定义属性,我会希望他们能够看到和编辑在DataGrid以及地板 。 我想我会落得这样做具有地板类实现IExtenderProvider。 所以,最后的DataGrid能是这个样子:

Initial Properties      Future Custom User Properties

Height    Elevation     ProgramType    UnitType  UnitCount  
15'       70'           Residential    Luxury    5
15'       55'           Residential    Luxury    5
15'       40'           Residential    Budget    10
20'       20'           Retail         N/A       2
20'       0'            Retail         N/A       3

我现在的问题是我应该立足我FloorList收集掉,让这个功能? 是我考虑的选项如下。

1)从列表中继承(楼层)

  • 法如添加/删除不vitrual,因此我无法不重写它们更新升高

2)实现IList(楼层)

  • OnChange事件没有内置,如果列表改变的DataGrid将不会更新(我想?)

  • 我想,这可能是最好的选择,但我需要做的确保到FloorList集合或DataGrid的变化与相互同步?

3)继承的BindingList(楼层)

  • 像添加/删除方法是不是虚拟的,所以我不能修改它们更新地面高程。

4)实现IBindingList的

  • IBindingList的是不通用的,我只希望我的收藏包含地面物体

Answer 1:

您应该使用的BindingList为您收集或实施IBindingList的,因为这会通知后面的DataGridView关于列表中的任何改变。

然后实现了地板类INotifyPropertyChanged接口,这将使您的个人项目落地和在DataGridView之间的双向绑定模式。

埃里克,你也可以做这样的事情

   public class MyFloorCollection : BindingList<Floor>
            {
                public MyFloorCollection()
                    : base()
                {
                    this.ListChanged += new ListChangedEventHandler(MyFloorCollection_ListChanged);

                }

                void MyFloorCollection_ListChanged(object sender, ListChangedEventArgs e)
                {

                 if (e.ListChangedType == ListChangedType.ItemAdded)
                 {

                    Floor newFloor = this[e.NewIndex] as Floor;

                    if (newFloor != null)
                    {
                        newFloor.HeightChanged += new Floor.HeightChangedEventHandler(newFloor_HeightChanged);
                    }
                  }

                }

                void newFloor_HeightChanged(int newValue, int oldValue)
                {
                    //recaluclate
                }


            }

当然,你可以创建自己的HeightChangedEvent和订阅,你不要这样具有通过属性名称中的if语句去。

所以,你的地板类将这个样子

 public class Floor : INotifyPropertyChanged
        {
            private int _height;

            public int Height
            {
                get { return _height; }
                set 
                {
                    if (HeightChanged != null)
                        HeightChanged(value, _height);

                    _height = value;
                    OnPropertyChanged("Height");

                }
            }




            public int Elevation { get; set; }

            private void OnPropertyChanged(string property)
            {
                if (this.PropertyChanged != null)
                    this.PropertyChanged(this, new PropertyChangedEventArgs(property));
            }

            #region INotifyPropertyChanged Members

            public event PropertyChangedEventHandler PropertyChanged;

            #endregion

            public delegate void HeightChangedEventHandler(int newValue, int oldValue);
            public event HeightChangedEventHandler HeightChanged;
        }

这样你只需要订阅的,而不是来的PropertyChanged你HeightChanged变量。 的PropertyChanged将由DataGridView的消耗,以保持一个双向绑定。 我相信这种方式是清洁的。

您还可以更改的委托,并通过该项目作为发件人。

public delegate void HeightChangedEventHandler(Floor sender, int newValue, int oldValue);

编辑:从HeightChanged事件退订,你需要重写的removeItem

  protected override void RemoveItem(int index)
        {
            if (index > -1)
                this[index].HeightChanged -= newFloor_HeightChanged;

            base.RemoveItem(index);
        }


Answer 2:

实现IList(楼),并有新的收藏也实现了INotifyPropertyChanged的接口。



Answer 3:

你可以尝试曝露出ObservableCollection<Floor>属性含有类的一些数据。 此外, Floor目标需要实现INotifyPropertyChanged支持双向从UI结合。



文章来源: Creating a custom collection that can be bound to a DataGrid