我工作的一个建筑公司工作,我创建一个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(楼层)
3)继承的BindingList(楼层)
- 像添加/删除方法是不是虚拟的,所以我不能修改它们更新地面高程。
4)实现IBindingList的
- IBindingList的是不通用的,我只希望我的收藏包含地面物体
您应该使用的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);
}
实现IList(楼),并有新的收藏也实现了INotifyPropertyChanged的接口。
你可以尝试曝露出ObservableCollection<Floor>
属性含有类的一些数据。 此外, Floor
目标需要实现INotifyPropertyChanged
支持双向从UI结合。