回复 寒枫天伤 - PSP 的问题
载体的设计有俩个思路,一个是表格式的,一个是层次的。
ms的ADO、DataSet就是表格式的,采用行、列组成的表,然后表集合之间建立联系。他更贴近关系型数据库的结构,因此使用简单、可以充分利用已经成熟的大量研究成果。缺点就是他是抽象的,不直观。
通常的xml和O/R的设计就是层次的,局部来说也是行(集合)、列(属性)组成表(对象),区别是表(对象)之间不是平等的关系,而是建立了有点像树一样的结构。好处吗,编写代码的时候看着舒服些罗(不是我打击你),缺点吗,一沓子了,我最头大的是数据跟踪问题。
我无法在一片文章中说明所有的事情,例如序列化、继承原则、CRUD、数据跟踪一大堆要处理的事情。
先说说 IBindList和ICancelAddNew接口吧,IBindList是列表绑定的基础接口,他继承于IList接口,如果你想绑定到某个表格或者列表中,IList基本上够了(实际上数组和ICollection也可以),但IBindList提供是否能新增、编辑和删除的选项,还提供排序、查找等功能(我可没有实现这个复杂的功能,我使用表格本身的功能),最重要的是他提供了ListChanged事件,这个是你通知外界你的集合发生改变的最好途径,所以你的集合最好是实现IBindList,而不紧紧是IList。
ICancelAddNew接口用在表格的编辑中,你使用表格的时候都知道你新建一行的时候可以按ESC键取消新建,实际内部的工作原理是:已经新建了行并添加到行集合,当你按ESC时,删除掉刚才的一行,所以你必须记住刚才新建的行是第多少行。
(如果没有记错的话,.net 1.1是没有这个接口的 ,.net 2.0才有)
下面的代码是部分的集合代码(不能运行的),不要以为我能写多好的程序,其实我是抄System.ComponentModel.Collections.Generic.BindingList<T>的。
Using directives#region Using directives
using System;
using System.Collections;
using System.ComponentModel;
using Mango.Common.Data;
using Mango.Common.Properties;
using System.Reflection;
#endregion
namespace Mango.Common.Data
{
/**//// <summary> 行集合对象的基础类 </summary>
public class DataRowCollectionBase : CollectionBase, IBindingList, IList, ICollection, IEnumerable, ICancelAddNew
{
// Fields
private int addNewPos;
private bool hookingItems;
private PropertyChangedEventHandler onItemPropertyChanged;
private bool allowNew;
private bool allowEdit;
private bool allowRemove;
private Type _itemType;
private object _parent;
// Events
public event AddingNewEventHandler AddingNew;
public event ListChangedEventHandler ListChanged;
类的初始化方法#region 类的初始化方法
/**//// <summary> 创建无父对象的集合 </summary>
public DataRowCollectionBase()
{
this.addNewPos = -1;
this.allowNew = true;
this.allowEdit = true;
this.allowRemove = true;
}
/**//// <summary> 创建集合,并为集合设置父对象 </summary>
public DataRowCollectionBase(object parent) :this()
{
_parent = parent;
}
#endregion
AddNew相关方法#region AddNew相关方法
/**//// <summary>
/// 获取集合类的名细类型
/// </summary>
protected virtual Type GetCollectionItemType()
{
if (_itemType == null)
{
Type collType = this.GetType();
object[] ps = collType.GetCustomAttributes(typeof(DbCollectionAttribute), true);
if (ps == null || ps.Length == 0)
throw new ApplicationException(string.Format(Resources.Error_NotSetDbCollAtt, collType.Name));
_itemType = ((DbCollectionAttribute)ps[0]).TypeContainedInCollection;
}
return _itemType;
}
/**//// <summary> 引发 AddingNew 事件 </summary>
protected virtual void OnAddingNew(AddingNewEventArgs e)
{
if (this.AddingNew != null)
{
this.AddingNew(this, e);
}
}
/**//// <summary> 返回新的对象 </summary>
private object FireAddingNew()
{
AddingNewEventArgs addNewArgs = new AddingNewEventArgs(null);
this.OnAddingNew(addNewArgs);
return addNewArgs.NewObject;
}
/**//// <summary> 在向 DataRowCollectionBase 实例中插入新元素之前执行其他自定义进程。 </summary>
protected override void OnInsert(int index, object value)
{
//检查新对象的父对象
DataRowBase row = value as DataRowBase;
if (row != null)
{
if (row.Parent != null)
throw new ArgumentException(Resources.Error_ColHaveParent);
}
this.EndNew(this.addNewPos);
this.HookItem(value, true);
base.OnInsert(index, value);
}
/**//// <summary> 在向 DataRowCollectionBase 实例中插入新元素之后执行其他自定义进程。 </summary>
protected override void OnInsertComplete(int index, object value)
{
//设置新对象的父对象
DataRowBase row = value as DataRowBase;
if (row != null)
row.SetParent(_parent);
base.OnInsertComplete(index, value);
this.FireListChanged(ListChangedType.ItemAdded, index);
}
/**//// <summary> 将新项添加到列表。</summary>
object IBindingList.AddNew()
{
object newObject = this.AddNewCore();
this.addNewPos = (newObject != null) ? base.List.IndexOf(newObject) : -1;
return newObject;
}
/**//// <summary> 将新项添加到列表。 </summary>
protected virtual object AddNewCore()
{
object newObject = this.FireAddingNew();
if (newObject == null)
{
newObject = Activator.CreateInstance(GetCollectionItemType());
//自动填充关键字
IDataRow dataRow = newObject as IDataRow;
if (dataRow != null)
{
DataRowType t = dataRow.GetDataRowType();
PropertyInfo pi = t.GetPrimaryKeyProperty();
pi.SetValue(dataRow, Guid.NewGuid().ToString("N"), null);
}
}
base.List.Add(newObject);
return newObject;
}
#endregion
ListChanged事件的支持#region ListChanged事件的支持
/**//// <summary> 引发 ListChanged 事件 </summary>
protected virtual void OnListChanged(ListChangedEventArgs e)
{
if (this.ListChanged != null)
{
this.ListChanged(this, e);
}
}
//内部引发ListChanged事件
private void FireListChanged(ListChangedType listChangedType, int index)
{
this.OnListChanged(new ListChangedEventArgs(listChangedType, index));
}
//内部引发ListChanged事件
private void FireListChanged(ListChangedType listChangedType, int index,string propertyName)
{
PropertyDescriptor propDesc = TypeDescriptor.CreateProperty(GetCollectionItemType(), propertyName,typeof(string), null);
this.OnListChanged(new ListChangedEventArgs(listChangedType, index,propDesc));
}
/**//// <summary> 返回/设置是否引发ListChanged中ItemChanged项目 </summary>
public bool RaiseItemChangedEvents
{
get
{
return this.hookingItems;
}
set
{
if (this.hookingItems != value)
{
this.HookItems(false);
this.hookingItems = value;
this.HookItems(true);
}
}
}
/**//// <summary> 引发重新更新事件 </summary>
public void ResetBindings()
{
this.FireListChanged(ListChangedType.Reset, -1);
}
/**//// <summary> 引发某个元素的改动事件 </summary>
public void ResetItem(int position)
{
this.FireListChanged(ListChangedType.ItemChanged, position);
}
//拦截/取消元素
private void HookItem(object item, bool hook)
{
if (!this.hookingItems)
{
return;
}
if (this.onItemPropertyChanged == null)
{
this.onItemPropertyChanged = new PropertyChangedEventHandler(this.OnItemPropertyChanged);
}
IPropertyChange tmp = item as IPropertyChange;
if (tmp != null)
{
if (hook)
tmp.PropertyChanged += this.onItemPropertyChanged;
else
tmp.PropertyChanged -= this.onItemPropertyChanged;
}
}
//拦截/取消指定索引的元素
private void HookItemAt(int index, bool hook)
{
if ((this.hookingItems && (index >= 0)) && (index < base.Count))
{
this.HookItem(base.List[index], hook);
}
}
//拦截/取消所有元素
private void HookItems(bool hook)
{
if (!this.hookingItems)
return;
IEnumerator e = base.GetEnumerator();
while (e.MoveNext())
{
object tmp = e.Current;
this.HookItem(tmp, hook);
}
}
//在元素发生改变时调用
private void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
this.FireListChanged(ListChangedType.ItemChanged, base.List.IndexOf(sender), e.PropertyName);
}
#endregion
Clear相关方法#region Clear相关方法
/**//// <summary> 在清除 DataRowCollectionBase 中所有实例之前执行其他自定义进程。</summary>
protected override void OnClear()
{
this.EndNew(this.addNewPos);
this.HookItems(false);
//删除父对象关联,注意:这里不能会滚操作
DataRowBase row;
foreach (object item in InnerList)
{
row = item as DataRowBase;
if (row != null)
row.SetParent(null);
}
base.OnClear();
}
/**//// <summary> 在清除 DataRowCollectionBase 中所有实例之后执行其他自定义进程。 </summary>
protected override void OnClearComplete()
{
base.OnClearComplete();
this.FireListChanged(ListChangedType.Reset, -1);
}
#endregion
Remove相关方法#region Remove相关方法
/**//// <summary> 在向 DataRowCollectionBase 实例中移出元素之前执行其他自定义进程。 </summary>
protected override void OnRemove(int index, object value)
{
this.EndNew(this.addNewPos);
this.HookItemAt(index, false);
base.OnRemove(index, value);
}
/**//// <summary> 在向 DataRowCollectionBase 实例中移出元素之后执行其他自定义进程。 </summary>
protected override void OnRemoveComplete(int index, object value)
{
//删除父对象关联
DataRowBase row = value as DataRowBase;
if (row != null)
row.SetParent(null);
base.OnRemoveComplete(index, value);
this.FireListChanged(ListChangedType.ItemDeleted, index);
}
#endregion
Set相关方法#region Set相关方法
/**//// <summary> 当在 DataRowCollectionBase 实例中设置值后执行其他自定义进程。</summary>
protected override void OnSetComplete(int index, object oldValue, object newValue)
{
//删除旧对象的父对象
DataRowBase oldRow = oldValue as DataRowBase;
if (oldRow != null)
oldRow.SetParent(null);
//设置新对象的父对象
DataRowBase newRow = newValue as DataRowBase;
if (newRow != null)
newRow.SetParent(_parent);
base.OnSetComplete(index, oldValue, newValue);
this.FireListChanged(ListChangedType.ItemChanged, index);
}
#endregion
ICancelAddNew支持#region ICancelAddNew支持
/**//// <summary> 取消新建的行 </summary>
public void CancelNew(int itemIndex)
{
if ((this.addNewPos >= 0) && (this.addNewPos == itemIndex))
{
this.RemoveAt(this.addNewPos);
this.addNewPos = -1;
}
}
/**//// <summary> 结束新建行的编辑 </summary>
public void EndNew(int itemIndex)
{
if ((this.addNewPos >= 0) && (this.addNewPos == itemIndex))
{
this.addNewPos = -1;
}
}
#endregion
集合是否可以改动的支持#region 集合是否可以改动的支持
/**//// <summary> 获取/设置是否可以使用 AddNew 向列表中添加项。 </summary>
public bool AllowNew
{
get
{
return ((IBindingList)this).AllowNew;
}
set
{
this.allowNew = value;
}
}
/**//// <summary> 获取是否可以使用 AddNew 向列表中添加项。 </summary>
bool IBindingList.AllowNew
{
get
{
return this.AllowNewCore;
}
}
/**//// <summary> 获取是否可以使用 AddNew 向列表中添加项。 </summary>
protected virtual bool AllowNewCore
{
get
{
return this.allowNew;
}
}
/**//// <summary> 获取/设置是否可更新列表中的项。 </summary>
public bool AllowEdit
{
get
{
return ((IBindingList)this).AllowEdit;
}
set
{
this.allowEdit = value;
}
}
/**//// <summary> 获取是否可更新列表中的项。</summary>
bool IBindingList.AllowEdit
{
get
{
return this.AllowEditCore;
}
}
/**//// <summary> 获取是否可更新列表中的项。 </summary>
protected virtual bool AllowEditCore
{
get
{
return this.allowEdit;
}
}
/**//// <summary> 获取/设置是否可以使用 Remove 或 RemoveAt 从列表中移除项。 </summary>
public bool AllowRemove
{
get
{
return ((IBindingList)this).AllowRemove;
}
set
{
this.allowRemove = value;
}
}
/**//// <summary> 获取是否可以使用 Remove 或 RemoveAt 从列表中移除项。 </summary>
bool IBindingList.AllowRemove
{
get
{
return this.AllowRemoveCore;
}
}
/**//// <summary> 获取是否可以使用 Remove 或 RemoveAt 从列表中移除项。 </summary>
protected virtual bool AllowRemoveCore
{
get
{
return this.allowRemove;
}
}
#endregion
排序和查询功能的支持#region 排序和查询功能的支持
/**//// <summary> 获取当列表更改或列表中的项更改时是否引发 ListChanged 事件。 </summary>
public bool SupportsChangeNotification
{
get
{
return this.SupportsChangeNotificationCore;
}
}
/**//// <summary> 获取当列表更改或列表中的项更改时是否引发 ListChanged 事件。 </summary>
protected virtual bool SupportsChangeNotificationCore
{
get
{
return true;
}
}
/**//// <summary> 获取列表是否支持使用 Find 方法进行搜索。 </summary>
public bool SupportsSearching
{
get
{
return this.SupportsSearchingCore;
}
}
/**//// <summary> 获取列表是否支持使用 Find 方法进行搜索。 </summary>
protected virtual bool SupportsSearchingCore
{
get
{
return false;
}
}
/**//// <summary> 获取列表是否支持排序 </summary>
public bool SupportsSorting
{
get
{
return this.SupportsSortingCore;
}
}
/**//// <summary> 获取列表是否支持排序 </summary>
protected virtual bool SupportsSortingCore
{
get
{
return false;
}
}
/**//// <summary> 获取是否对列表中的项进行排序。</summary>
public bool IsSorted
{
get
{
return this.IsSortedCore;
}
}
/**//// <summary> 获取是否对列表中的项进行排序。 </summary>
protected virtual bool IsSortedCore
{
get
{
return false;
}
}
/**//// <summary> 获取正在用于排序的 PropertyDescriptor。 </summary>
public PropertyDescriptor SortProperty
{
get
{
return this.SortPropertyCore;
}
}
/**//// <summary> 获取正在用于排序的 PropertyDescriptor。 </summary>
protected virtual PropertyDescriptor SortPropertyCore
{
get
{
return null;
}
}
/**//// <summary> 获取排序的方向。 </summary>
public ListSortDirection SortDirection
{
get
{
return this.SortDirectionCore;
}
}
/**//// <summary> 获取排序的方向。</summary>
protected virtual ListSortDirection SortDirectionCore
{
get
{
return ListSortDirection.Ascending;
}
}
/**//// <summary> 根据 PropertyDescriptor 和 ListSortDirection 对列表进行排序。 </summary>
public void ApplySort(PropertyDescriptor property, ListSortDirection direction)
{
this.ApplySortCore(property, direction);
}
/**//// <summary> 根据 PropertyDescriptor 和 ListSortDirection 对列表进行排序。 </summary>
protected virtual void ApplySortCore(PropertyDescriptor property, ListSortDirection direction)
{
throw new NotSupportedException();
}
/**//// <summary> 使用 ApplySort 移除任何已应用的排序。 </summary>
public void RemoveSort()
{
this.RemoveSortCore();
}
/**//// <summary> 使用 ApplySort 移除任何已应用的排序。</summary>
protected virtual void RemoveSortCore()
{
throw new NotSupportedException();
}
/**//// <summary> 返回具有给定 PropertyDescriptor 的行的索引。 </summary>
public int Find(PropertyDescriptor property, object key)
{
return this.FindCore(property, key);
}
/**//// <summary> 返回具有给定 PropertyDescriptor 的行的索引。 </summary>
protected virtual int FindCore(PropertyDescriptor property, object key)
{
throw new NotSupportedException();
}
/**//// <summary> 将 PropertyDescriptor 添加到用于搜索的索引 </summary>
void IBindingList.AddIndex(PropertyDescriptor property)
{
//
}
/**//// <summary> 从用于搜索的索引中移除 PropertyDescriptor。 </summary>
void IBindingList.RemoveIndex(PropertyDescriptor property)
{
//
}
#endregion
}
}
回复 寒枫天伤 - PSP 的问题相关推荐
- 关于PagedDataSource
原文地址:关于PagedDataSource 作者:秋天の风 关于PagedDataSource,非常好用的一个分页属性! Asp.net提供了三个功能强大的列表控件:DataGrid.DataLi ...
- 基类与接口混合继承的声明问题 [C#, Design] -Allen Lee's Magic
Updated on Friday, November 19, 2004 Written by Allen Lee 1. 问题初现 今天,查看<接口继承的声明问题>一文的反馈,发现Ninp ...
- 遍历ArrayList易犯错误
场景: 将ArrayList中符合条件的记录删掉,第一时间写出的程序如下: foreach (string aStr in aList) { ...
- windows网络服务之配置网络负载均衡(NLB)群集
O首页51CTO博客我的博客搜索 每日博报 社区:学院论坛博客下载更多 登录注册 家园 学院 博客 论坛 下载 自测 门诊 周刊 读书 技术圈 曾垂鑫的技术专栏 http://5 ...
- 体育门户里杀出的程咬金:虎扑凭什么?
概述:与新浪在体育报道领域扮演的"传统媒体"角色相比,虎扑也许算是体育报道界的"先知".早在十年前,虎扑就在发展论坛和大大小小的线下活动,尝试挖掘新媒体特性来获 ...
- 写在马哥教育第八期开始之前
"你不能剥夺别人思考的权力"!记得读研期间一位导师在谈到"传道.授业.解惑"时特地强调.当时身为学生,并未能完全.真切地理解这位导师表述的真正意图.而当自己独立 ...
- 灵动微电子逐飞 智能车支持计划汇总
▌灵动技术培训 直播简介:MM32 MCU系列产品简介和MM32SPIN27PF. MM32F3277G9P产品的详细介绍,MM32 MCU开发工具与智能车大赛的入门指导,包括MM32 MCU资料 ...
- 安装oracle 11gR2单实例+ASM
安装oracle11gR2单实例+ASM,让新手走向数据库管理员 一.介绍 因业务需要,最近在主系统的基础上搭建一套mini系统,本文只讲ORACLE数据库+ASM磁盘管理工具的安装: 1.服务器系统 ...
- 弱鸡儿长乐爆肝旅Day8
T1远征(expedition) [题目描述] 寒枫将军将要带领他的部队去圣雪山消灭那里的冰龙. 部队分成了若干个小队,属于同一个小队的人兵种相同.寒枫将军有着杰出的指挥能力,在战斗的时候,寒枫将军能 ...
最新文章
- MySql 查询表字段数
- (转)详解css3弹性盒模型(Flexbox)
- 最喜欢随机森林?周志华团队DF21后,TensorFlow开源决策森林库TF-DF
- linq TO XML 基础
- Linux系统调用的运行过程【转】
- poj 1845 Sumdiv (算数基本定理+逆元)
- Python 把较长的一行代码分成多行的技巧
- BOM--window对象
- Sql UNION 合并多个结果集并排序
- android 扫雷小游戏
- linux阅读文件格式,Linux下安装boox viewer阅读pdg格式文件
- python用实现FGO自动挂机战斗思路
- *新手看php手册的正确姿势
- 大数据影响下的专题地图编制
- Shell 千分 逗号隔开
- cad能整体比例缩小吗_cad怎么把原尺寸图缩小几倍
- 为什么程序员应该写博客?用什么博客系统?在哪写?
- 遇见Laravel Migrations的migrate与rollback
- 京东云加速扩展“朋友圈” 火力全开大展生态“云”图
- 生命的法则——植渝轩语录