感谢谭振林先生所著《道不远人——深入解析ASP.NET 2.0控件开发》
讨论完了功能,我们来思考一下这个控件应该怎么设计。
1,给控件取个名字吧,因为一开始小凡只是考虑了自动勾选功能,所以就叫它AutoCheckTreeView。
2,显然继承自TreeView要比重新做一个更方便,那好,AutoCheckTreeView : TreeView就这么决定了。
3,它要开放一些什么新增接口吗?想一下,有的时候需要自动勾选功能,有的时候不需要自动勾选,那应该留下一个开关属性。
4,数据绑定,那比如要重载DataSource属性和DataBind()方法喽。
5,我们不能要求用户必须以规定的格式数据源来绑定我们的控件,所以,我们需要用户告诉我们,哪个字段或者属性代表主键,哪个字段或者属性代表父主键,并且就像DropDownList一样,要有一个TextMember来告诉我们到时候节点显示哪个字段里面的内容。
6,如果绑定的数据源是DataSet,那我们还需要知道是绑定其中是哪个表。
7,为了节省用户劳动,我们可以把节点选择后的动作TreeNodeSelectAction添加作为一个公开属性,当绑定数据后,我们就可以把节点生成为该类型。
因此,所有的接口属性和公开方法就是如下:
- #region 变量
- private string dataPropertyName = String.Empty;
- /// <summary>
- /// 获取和设置单条数据中用于结构关系的列名或者属性名
- /// </summary>
- [Description("单条数据中用于结构关系的列名或者属性名"), DefaultValue("")]
- public string DataPropertyName
- {
- get
- {
- return ViewState["dataPropertyName"] == null ? dataPropertyName : ViewState["dataPropertyName"].ToString();
- }
- set
- {
- dataPropertyName = value;
- ViewState["dataPropertyName"] = value;
- }
- }
- private string dataParentPropertyName = String.Empty;
- /// <summary>
- /// 获取和设置单条数据中用于结构关系的父数据列名或者属性名
- /// </summary>
- [Description("单条数据中用于结构关系的父数据列名或者属性名"), DefaultValue("")]
- public string DataParentPropertyName
- {
- get
- {
- return ViewState["dataParentPropertyName"] == null ? dataParentPropertyName : ViewState["dataParentPropertyName"].ToString();
- }
- set
- {
- dataParentPropertyName = value;
- ViewState["dataParentPropertyName"] = value;
- }
- }
- private string tableName = String.Empty;
- /// <summary>
- /// 获取和设置表名称,用于当数据源为DataSet类型时
- /// </summary>
- [Description("表名称,用于当数据源为DataSet类型时"), DefaultValue("")]
- public string TableName
- {
- get
- {
- return ViewState["tableName"] == null ? tableName : ViewState["tableName"].ToString();
- }
- set
- {
- tableName = value;
- ViewState["tableName"] = value;
- }
- }
- private string textMember = String.Empty;
- /// <summary>
- /// 获取和设置数据绑定时用户设置TEXT值的字段或属性名
- /// </summary>
- [Description("数据绑定时用户设置TEXT值的字段或属性名"), DefaultValue("")]
- public string TextMember
- {
- get
- {
- return ViewState["textMember"] == null ? textMember : ViewState["textMember"].ToString();
- }
- set
- {
- textMember = value;
- ViewState["textMember"] = value;
- }
- }
- private Object dataSource = null;
- /// <summary>
- /// 设置和获取数据源,已重写
- /// </summary>
- [Description("数据源,已重写"), DefaultValue(null)]
- public new Object DataSource
- {
- get
- {
- return ViewState["dataSource"] == null ? dataSource : ViewState["dataSource"];
- }
- set
- {
- dataSource = value;
- ViewState["dataSource"] = value;
- }
- }
- TreeNodeSelectAction nodeSelectAction = TreeNodeSelectAction.Select;
- /// <summary>
- /// 设置和获取树节点选择后将引发事件
- /// </summary>
- [Description("树节点选择后将引发事件"), DefaultValue(TreeNodeSelectAction.Select)]
- public TreeNodeSelectAction NodeSelectAction
- {
- get
- {
- return ViewState["nodeSelectAction"] == null ? nodeSelectAction : (TreeNodeSelectAction)ViewState["nodeSelectAction"];
- }
- set
- {
- nodeSelectAction = value;
- ViewState["nodeSelectAction"] = value;
- }
- }
- private bool isAutoCheck = false;
- /// <summary>
- /// 设置和获取是否自动改变父子节点勾选状态
- /// </summary>
- [Description("是否自动改变父子节点勾选状态"), DefaultValue(false)]
- public bool IsAutoCheck
- {
- get
- {
- return ViewState["isAutoCheck"] == null ? isAutoCheck : (bool)ViewState["isAutoCheck"];
- }
- set
- {
- isAutoCheck = value;
- ViewState["isAutoCheck"] = value;
- }
- }
- #endregion
- /// <summary>
- /// 将数据源进行绑定并显示
- /// </summary>
- public void BindData()
幸好TreeView是支持ViewState的,我们要将这些属性值信息记录在ViewState中,这样页面回传之后就不需要用户重新赋值绑定了。