WPF DataGriw采用编辑模式,用户可以双击最尾的空白行从而新加一条记录.也可以选择行记录后按键盘Del键来删除选择的记录,做完一系列的操作后一次性把数据都保存到远程数据库中.那在MVVM中Ui和后台是分离的.不能直接知道那样那数据是新加\还是修改\有那些数据是被删除的了.那当前操作的集合表面保存的数据就不一定是这次一系列所有操作的数据.那只是操作过后所要保留下来的数据而以.为了触屏这样子的问题很多人一般都会写多几个按钮(如下图).把相应的操作都进行记录下来.这本来也不是什么不好的解决方法.但要是DataGrid这控件本来就是使用方便.管理数据还要这么多要求.那就有点偏离了这个控件的使用要求了.
这样的事情只有一两个业务单据就没什么.如果出现很多那就死得人多了.加上如果MVVM是操作的话大大加深了UI与后台的藕合度这可不利于维护的.出于项目功能还是自己写一个对应的集合吧.那自己写集合当然是要了我解集合所用到的接口DataGrid对操作要用到那些接口.写集合一般用到的接口或者说我们平时用到的List<T>这个数据集合是对实现了主要两个接口的分支IList<T>, IList这两个接口前者要做的是对泛型的管理(只管增删),后者是对Ojbect的管理(管增删之余还有属性说明这个合集是否固定长度[IsFixedSize],是否只读[IsReadOnly]). 那自定义的集合类最基本要实现的接口IList<T>, IList这两个接口下的所有方法.[ IsFixedSize]属性让DataGrid集合容器知道当前数据集合是否可以添加\删除.那我们就继承这两个接口定义我们新的接口. 使用我们在新增时可付默认值,删除时可以验证数据是否删除.这两功能采用委托方法.为什么是委托而不是事件.个人觉得只有一个地方执行就够.没必要在这付点默认值在那个地方付点默认值.删除也是一样在一个地方控制就行了.
public class ActionList<T> : IActionList<T>,IActionList, INotifyCollectionChanged
{
public ActionList();
public ActionList(IEnumerable<T> collection);
}
构造函数说明.一个为空的构造函(这个原空集合最后所才生的都是要添增的数据),有参数的构造函数(集合最后保留的数据参数的默认为修改的集合中,如果有删除操作记录则移到移除集合中.如有添就新的则为新增的记录)
只于为什么要加上INotifyCollectionChanged主要是为了MVVM模式下UI可以及时更新显示数据,事件的构造函数如果为了能在Silverlight上也通用的话,基本上是要采用多参数,有些动作在Silverlight也不存在只要4个动作类型[Add,Remove,Reset,Replace].为能了一个文件通用往往会加入#if !SILVERLIGHT来判断编译环境.Silverlight中只有3种事件的构造函数,比起WPF上的12种就真的简单很多了.在本编中用到3个参数的(动作[只能Add,Remove],数据,索引)的函数来处理增删,[Reset]动作只能用单个参数的.[Replace]动作则要用到4个参数的.
本来是泛型的集合类所以都是围绕着List<T>这个字段来操作.IActionList<T>接口为主要实现,IActionList则为显式实现.普通的接口实现与显式实现的区别在于显式实际的接口在调用实现类时,现实类是不会见到对应的属性和方法只有转换成接口时才能调用,从实现类可以选择性的暴露相关属性和方法更好的突出实现类自己的特性.不足之点就是都要实现功能不像继承那可以什么都不用写.
在什么时候往我们定义的集合中添加数据呢.由于框架所有的数据集合处理都是基本IList接口的(还真的不知道为什么没有IList<T>接口,但有实现IList<T>接口的类就一定会实现IList,所以最终处理的都是IList接口我觉得可能IList是对数据没有约束性更符合所有类型都派生于Object对象吧),所以我们主要是在IList接口中的Add,Remove处理前还要执行我们的委托判断.处理时把数据判断好分类放入对应的数据集合中就行了.处理后当然要加上对就的INotifyCollectionChanged事件前台UI才会跟着变.这样子委托有值时就会执行委托生成默认值或者判断当前记录是否真的要删除.操作了又会在对应的数据集合中添加上对应的数据.前台UI也会更着变化.
由于INotifyCollectionChanged不支持数组的事件采用数组会有异常(Silverlight没有对应的方法传参数UI只会变化第一条记录,而WPF下有对应的参数但前台UI更新数据时提示不支持集合的变化直接出现异常错误死了).如果在写数组操作时要用循环把数组中的数据一条条执行事件更新到前台UI中.
平时用到的集合最后还是依赖于IList而泛型只是为了数据的直观\操作的方便进行二次封装而以.什么Array\ArrayList\List<T>\CollectionBase\Object[]都是实现IList接口,不过数组是个比较特别的集合通过Array抽象类和编译器动态生成的.能通过数据查到所用的方法和属性都来源自Array抽象类,但在Array抽象类中则找到相关的派生类.