创建可以绑定到DataGrid自定义集合 [英] Creating a custom collection that can be bound to a DataGrid

查看:254
本文介绍了创建可以绑定到DataGrid自定义集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I work for an Architecture firm and I am creating a plug-in for a 3D modeling program to assist design. I have a Building class, and a Floor class. The building contains a reference to a FloorList collection of floors. I'm trying to figure out what to base the FloorList collection off of so that I can minimize the amount of work I need to do to create an interface to edit the collection.

地板收集再presents一系列堆叠在彼此顶部建筑楼层。每个地板有一个 Floor.Height 是读写性能,以及 Floor.Elevation 是只读的,通过设置共计地板财产低于目前的地板高度即可。所以,当一个地板中添加,删除,移动或集合中改变的 Floor.Elevation 属性需要进行更新。

The Floor collection represents a series of building floors that are stacked on top of one another. Each Floor has a Floor.Height property that is read write, and an Floor.Elevation property that is read only and set by totaling the floor heights below the current Floor. So, whenever a Floor is added, removed, moved, or changed in the collection the Floor.Elevation properties need to be updated.

另外,我想创建一个UI编辑此集合。我想使用的的DataGrid 控制每个地板列出了它的高度等性能作为控制的一排。用户应该能够添加,删除,并重新使用控制命令地板。我想设置此功能是为方便和灵活越好。这意味着我想简单地能够楼层收集绑定到的DataGrid 并有列在的DataGrid 根据楼的属性填充类。如果可能的话我希望能够利用内置在添加/删除与具有惹出来与设置了一堆事件的关系我的收藏和的DataGrid 之间的DataGrid控件的UI界面。

In addition, I want to create a UI to edit this collection. I was thinking of using a DataGrid control where each Floor is listed with its Height and other properties as a row of the control. The user should be able to add, remove, and re order floors using the control. I'd like setting this up to be as easy and flexible as possible. Meaning I'd like to simply be able to bind the collection of Floors to the DataGrid and have the columns of the DataGrid populate based on the properties of the Floor class. If possible I'd like to be able to utilize the built in Add/Remove UI interface of the DataGrid control with out having to mess with setting up a bunch of event relationships between my collection and the DataGrid.

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

To complicate things further in the future I'll need to be able to allow the user to dynamically add custom properties to the Floors that I'll want them to be able to see and edit in the DataGrid as well. I think I'd end up doing that by having Floor class implement IExtenderProvider. So ultimately the DataGrid would look something like this:


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 收集掉,让这个功能?是我考虑的选项如下:

My question now is what should I base my FloorList collection off of to allow for this functionality? The options I'm considering are as follows.

1)从名单继承(楼)


  • 方法,如添加/删除不vitrual,因此我不能没有覆盖他们更新了海拔

2)实现IList(楼)


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

  • OnChange event is not built in so if the lists changes the DataGrid will not update (I think?)

我想,这可能是最好的选择,但我需要做的确保变更的 FloorList 收集或的DataGrid 会被同步彼此

I think this is probably the best option but what would I need to do the ensure that changes to the FloorList collection or DataGrid are synced with one another?

3)的BindingList(楼)继承


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

4)实施IBindingList的


  • IBindingList的是不通用的,我只希望我的收藏包含的地板对象

  • IBindinglist is not generic and I only want my collection to contain Floor objects

推荐答案

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

You should use BindingList for your collection or implement IBindingList as this will notify back the DataGridView about any changes in the list.

然后落实地板类INotifyPropertyChanged接口,这将允许你个人的楼项目,并在DataGridView之间的双向绑定模式。

Then implement INotifyPropertyChanged interface for Floor class, this will allow for a TwoWay binding mode between your individual Floor items and the DataGridView.

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

Eric, you could also do something like this

   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语句中去。

Of course you can create your own HeightChangedEvent and subscribe to that, that way you dont have to go by property names in an if statement.

所以,你的地板类看起来像这样

So your Floor class will look like this

 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的消耗保持双向绑定。我相信这种方式是清洁的。

this way you only have to subscribe to your HeightChanged variable, instead of to PropertyChanged. PropertyChanged will be consumed by the DataGridView to keep a TwoWay binding. I do believe this way is cleaner.

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

You can also change the delegate and pass the item as the sender.

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

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

To unsubscribe from HeightChanged event you need to override RemoveItem

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

            base.RemoveItem(index);
        }

这篇关于创建可以绑定到DataGrid自定义集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆