• DataControlField与Parameter扩展


           示例代码请参考此篇


    一.为数据绑定控件(GridView)自定义列(DataControlField)

    本来asp.net1.1中已经存在DataGrid了,其中为我们提供了丰富的数据字段类型(即不同绑定列),如下代码

                <asp:DataGrid ID="dg1" runat="server">
                
    <Columns>
                
    <asp:BoundColumn></asp:BoundColumn>
                
    <asp:ButtonColumn></asp:ButtonColumn>
                
    <asp:HyperLinkColumn></asp:HyperLinkColumn>
                
    <asp:TemplateColumn></asp:TemplateColumn>
                
    </Columns>
                
    </asp:DataGrid>
    网上也有介绍扩展DataGridColumn类的方法,asp.net2.0新增的GridView定义了全新的数据列,其也可以用于DetailsView,即DataControlField类

    来看下其内置列的实现



    DataControlField类为数据列的基类,其派生类相信大家都很熟悉,如下图



    当然我们这里讨论的不是怎么使用这些列,而是如何实现自定义列的过程.实现方法跟以前的有些相似,还是抽象类DataControlField为我们实现了一些常用方法,并定义了一些必须让我们去实现的方法,让字类去重写.

    下面列出常用相关的方法

    这里以自定义CalendarField列为例

    看DataControlField的CloneField()方法,先创建对象,再复制属性
        protected internal DataControlField CloneField()
        
    {
            DataControlField newField 
    = this.CreateField();
            
    this.CopyProperties(newField);
            
    return newField;
        }



    1.创建列对象

    DataControlField提供了CopyProperties 方法,此工作一定要做

            protected override DataControlField CreateField()
            
    {
                
    return new CalendarField();
            }


    2.复制属性

    DataControlField提供了CopyProperties 方法

    首先要先定义你需要的属性,然后将属性复制给CloneField方法中创建的对象,在更改属性时要记得调用OnFieldChanged方法,通知DataControlField对象状态发生变化,触发FieldChanged事件


    3.初始化单元格状态(InitializeCell方法)

    即把你自己定义的东西添加到表格中。这里需要注意顺序

    我们知道GridView的单元格(即DataControlCellType)分为三种类型,页眉,页脚,数据项,到了确定是数据项以后,又要给数据行分类型

    如编辑,插入,交替,选中等(即DataControlRowState)

    BoundField在普通状态下是文本,在编辑状态下是TextBox.这里就是要做这个工作,在不同状态下,加载不同控件。如下代码

          public override void InitializeCell(DataControlFieldCell cell, DataControlCellType cellType, DataControlRowState rowState, int rowIndex)
            
    {

                
    base.InitializeCell(cell, cellType, rowState, rowIndex);

                
    //如果为数据项
                if (cellType == DataControlCellType.DataCell)
                    InitializeDataCell(cell, rowState);
            }


            
    protected virtual void InitializeDataCell(DataControlFieldCell cell, DataControlRowState rowState)
            
    {
                Control ctrl 
    = null;

                DataControlRowState state 
    = rowState & DataControlRowState.Edit;

                
    //根据状态加载不同控件
                if ((!ReadOnly && (state != DataControlRowState.Normal)) || rowState == DataControlRowState.Insert)
                
    {
                    Calendar cal 
    = new Calendar();
                    cal.ToolTip 
    = this.HeaderText;
                    cell.Controls.Add(cal);

                    
    if ((DataField.Length != 0&&
                        (DataField.Length 
    != 0))
                        ctrl 
    = cal;

                    _inInsertMode 
    = rowState == DataControlRowState.Insert;
                }

                
    else if (DataField.Length != 0)
                
    {
                    ctrl 
    = cell;
                }


                
    //给控件赋绑定的值
                if ((ctrl != null&& Visible)
                
    {
                    ctrl.DataBinding 
    += new EventHandler(this.OnBindingField);
                }

            }

    4.实现数据交互(ExtractValuesFromCell方法)

    第三步骤是显示信息,这里则需要提取字段的值,然后添加到dictionary集合中.具体其他操作暂且不管。

            public override void ExtractValuesFromCell(IOrderedDictionary dictionary, DataControlFieldCell cell, DataControlRowState rowState, bool includeReadOnly)
            
    {
                
    object selectedValue = null;
                
    if (cell.Controls.Count > 0
                
    {
                    Calendar cal 
    = cell.Controls[0as Calendar;

                    
    if (cal == null)
                    
    {
                        
    throw new InvalidOperationException("CalendarField could not extract control.");
                    }

                    
    else
                        selectedValue 
    = cal.SelectedDate;
                }


                
    // Add the value to the dictionary
                if (dictionary.Contains(DataField))
                    dictionary[DataField] 
    = selectedValue;
                
    else
                    dictionary.Add(DataField, selectedValue);
            }

    5.给列添加设计时支持

    BoundField列在有字段绑定的情况下,在设计时显示如下



    其是通过GetDesignTimeValue方法实现的,如可以这样定义

            protected virtual string GetDesignTimeValue()
            
    {
                
    return "<select><option>Databound Date</option></select>";
            }

    在页面效果如下

     

    好了,大致步骤就如此,你只需要熟悉上面方法,照着步骤做一遍就可以了.
    另外还有DataGrid的DataGridColumn,如果你理解上面DataControlField的做法的话,DataGridColumn的实现关键方法则是InitializeCell,方法比较相似.但其没有ExtractValuesFromCell方法,因为DataGrid当时还没有这么的智能化的自动编辑功能.

    二.数据源控件控件自定义参数

    数据源控件我们也比较常用,所以要学习下如何自定义参数,如下图,为内置已经实现的几个参数类.



    我们还是关注下Parameter类,其主要提供了一个空的Evaluate 方法给,派生类需要实现此方法返回经过更新的值.其实现比较简单,来看下其内部QueryStringParameter的实现过程.应该说没什么难度.抓住重点就好


    public class QueryStringParameter : Parameter
    {
            
    public QueryStringParameter()
        
    {
        }


        
    protected QueryStringParameter(QueryStringParameter original) : base(original)
        
    {
            
    this.QueryStringField = original.QueryStringField;
        }


        
    public QueryStringParameter(string name, string queryStringField) : base(name)
        
    {
            
    this.QueryStringField = queryStringField;
        }


        
    public QueryStringParameter(string name, TypeCode type, string queryStringField) : base(name, type)
        
    {
            
    this.QueryStringField = queryStringField;
        }


        
    protected override Parameter Clone()
        
    {
            
    return new QueryStringParameter(this);
        }


        
    protected override object Evaluate(HttpContext context, Control control)
        
    {
            
    if ((context != null&& (context.Request != null))
            
    {
                
    return context.Request.QueryString[this.QueryStringField];
            }

            
    return null;
        }


            
    public string QueryStringField
        
    {
            
    get
            
    {
                
    object obj2 = base.ViewState["QueryStringField"];
                
    if (obj2 == null)
                
    {
                    
    return string.Empty;
                }

                
    return (string) obj2;
            }

            
    set
            
    {
                
    if (this.QueryStringField != value)
                
    {
                    
    base.ViewState["QueryStringField"= value;
                    
    base.OnParameterChanged();
                }

            }

        }

    }



    三.属性集合

    以上的
    DataControlFieldParameter都具有集合类型DataControlFieldCollectionParameterCollection

    有时候扩展了以后可能还需要更改集合类型,因为有时候集合类型是在开发人员在功能已经实现的情况下编写的.现在的扩展势必需要发生一些改变.而属性类型一更改,控件内部的集合属性也需要更改.当然偷懒的话就不改了,这么一改比较麻烦.但这种事情还是会碰到的.这里就提一下.

    好了就这么写一下,希望对大家有帮助.本人已经在上海的某家公司工作.
    今后的工作大多会更多地设计到控件的开发上,希望与大家多交流
  • 相关阅读:
    web端常见兼容性问题整理
    浏览器初始化样式
    html5特效库
    csshack
    进程与线程,并发、并行、异步、多线程
    js复制粘贴事件
    dom range相关
    vue和react在使用上的对比
    ListView往TreView里面拖拽
    ListView添加项目带序列
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/771913.html
Copyright © 2020-2023  润新知