zoukankan      html  css  js  c++  java
  • asp.net控件开发基础(21)

           示例代码

           上篇介绍了在asp.net2.0版本下面如何简单的定义数据绑定控件。虽然DataBoundControl为我们提供了便利,我们以后可以从此类开始编写数据绑定控件。但是在2.0版本未到来之前,你已经为自己订制了一些数据绑定控件,既然2.0版本已经提供了数据源控件,你是否有想法,让你原有的控件也升级到同时支持通过设置DataSource属性和数据源控件来获取数据源,这样以后我们就可以省省工作了。这次我们就来讨论这个话题,让旧版本的数据绑定控件支持数据源控件

    一.准备升级数据绑定控件

    即使asp.net1.1版本的一些控件也都已经支持数据源控件了,如Repeater,BaseDataList等.但本身这些对象并不是从BaseDataBoundControl和DataBoundControl等类继承下来的,如Repeater其是从Control下继承的一个模板控件,其并不需要这么多从WebControl继承下来的属性,如果你想让它支持数据源控件,你首先会想到改变控件基类,从DataBoundControl开始,这是一个好想法,但可能有些情况下并不允许这么做。上次说到了BaseDataList和DataBoundControl,BaseDataList也支持数据源控件了,所以我认为从此类继承是完全没有问题的。另外的做法就是在不改变原有控件基类的情况下,你还是需要老老实实给原控件添加一些代码支持数据源控件。那么就开始吧.

    二.具体实现

    本次例子跟上篇相同,相同地方就略过了

    1.定义基本成员

    整个控件的实现方式跟DataBoundControl实现方式很相似,我们可以看看MSDN中,BaseDataList等基类添加了哪些元素,然后模仿着实现.如果对BaseDataBoundControl和DataBoundControl这两个类成员了解的话,你将对下面成员属性很熟悉,添加这些基本成员


    (1)



    (2)上面几个属性涉及到几个方法


    上面的几个属性和方法可以一起来看看了,在更改数据源标识时都会调用OnDataPropertyChanged方法,然后到了EnsureDataBound方法(此方法在OnPreRender方法中调用)在使用数据源控件情况下自动调用DataBind方法。另外Initialized属性会在控件初始化时设置.


    2.获取与数据绑定控件关联的IDataSource 接口
    数据源控件实现了IDataSource接口,此接口定义了数据源最基本的元素,数据绑定控件要根据DataSourceID属性从容器中获取与其关联的 IDataSource 接口。如下实现

         // 从容器中获取DataControl
           private Control FindControl(Control control, string controlID)
            
    {
                Control namingContainer 
    = control;
                Control dataControl 
    = null;
                
    if (control != control.Page)
                
    {
                    
    while ((dataControl == null&& (namingContainer != control.Page))
                    
    {
                        namingContainer 
    = namingContainer.NamingContainer;
                        
    if (namingContainer == null)
                        
    {
                            
    throw new HttpException("DataBoundControlHelper_NoNamingContainer");
                        }

                        dataControl 
    = namingContainer.FindControl(controlID);
                    }

                    
    return dataControl;
                }

                
    return control.FindControl(controlID);
            }


            
    /// <summary>
            
    /// 检索与数据绑定控件关联的 IDataSource 接口
            
    /// </summary>
            
    /// <returns></returns>

           protected virtual IDataSource GetDataSource()
           
    {
               
    if (this.currentDataSource != null)
               
    {
                   
    return currentDataSource;
               }


               
    //获取数据源控件
               IDataSource source = null;
               
    string controlID = DataSourceID;
               
    if (controlID.Length != 0)
               
    {
                   Control control 
    = FindControl(this, controlID);
                   source 
    = control as IDataSource;
               }

               
    return source;
           }

    3.获取数据源视图

    第二步的实现是为此服务的

            private DataSourceView ConnectToDataSourceView()
            
    {

                
    if (!currentViewValid || base.DesignMode)
                
    {
                    
                    
    if ((currentView != null&& currentViewIsFromDataSourceID)
                    
    {
                        currentView.DataSourceViewChanged 
    -= new EventHandler(this.OnDataSourceViewChanged);
                    }


                    
    this.currentDataSource = GetDataSource();

                    
    //从DataSource获取数据源
                    if (this.currentDataSource == null)
                    
    {
                        
    this.currentDataSource = new ReadOnlyDataSource(DataSource, DataMember);
                    }


                    DataSourceView view 
    = this.currentDataSource.GetView(DataMember);
                    currentViewIsFromDataSourceID 
    = IsBoundUsingDataSourceID;
                    currentView 
    = view;
                    
                    
    if ((currentView != null&& currentViewIsFromDataSourceID)
                    
    {
                        currentView.DataSourceViewChanged 
    += new EventHandler(this.OnDataSourceViewChanged);
                    }

                    currentViewValid 
    = true;
                }

                
    return currentView;
            }


            
    /// <summary>
            
    /// 获取数据源视图
            
    /// </summary>
            
    /// <returns></returns>

            protected virtual DataSourceView GetData()
            
    {
              
    return ConnectToDataSourceView();
            }


    请注意ConnectToDataSourceView方法,前后分别在移除和添加一个事件,将RequiresDataBinding属性设置为true重新绑定,然后再看中间这段代码

                    if (this.currentDataSource == null)
                    
    {
                        
    this.currentDataSource = new ReadOnlyDataSource(DataSource, DataMember);
                    }

    即当未使用数据源控件时,则就从ReadOnlyDataSource对象通过设置DataSource和DataMember属性来获取IDataSource 接口,然后才能获取到数据源视图.下面为ReadOnlyDataSource和ReadOnlyDataSourceView的简单实现,在此不做解释.下次再来讲这个东西



    4.获取数据

    接着你便可以在DataBind方法中通过获取到的数据源视图异步获取数据了,本来我们可以调用其ExecuteSelect方法的,可惜我们无法调用此方法,只好异步调用。接着的PerformDataBinding方法跟上篇实现一样。不再列出

    记得在DataBind方法将RequiresDataBinding 属性设置为true


            /// <summary>
            
    /// 将数据源绑定到控件
            
    /// </summary>

            public override void DataBind()
            
    {
                
    if (!IsBoundUsingDataSourceID)
                
    {
                    OnDataBinding(EventArgs.Empty);
                }


                GetData().Select(CreateDataSourceSelectArguments(),
                    OnDataSourceViewSelectCallback);
                RequiresDataBinding 
    = false;
                MarkAsDataBound();
            }

            
    private void OnDataSourceViewSelectCallback(IEnumerable retrievedData)
            
    {
                
    if (IsBoundUsingDataSourceID)
                
    {
                    OnDataBinding(EventArgs.Empty);
                }

                PerformDataBinding(retrievedData);
            }

    5.重写控件生命周期事件

    其中在OnPreRender方法中调用了EnsureDataBound方法,其他方法的话可以发现在很多不同情况下将RequiresDataBinding和Initialized属性设置为True.做了数据绑定的初始化工作。这里估计我也解释不清楚,大家还是了解下控件的生命周期,了解其事件的使用,再理解吧.这里可以参考jessezhao的这篇翻译


    好了,基本代码的编写就完成了,接着你就可以通过设置DataSource属性手动绑定的形式和设置DataSourceID属性获取数据源的形式获取数据了。

    这篇可以供参考,如果真要这么做的话,几乎每个原有的数据绑定控件都需要重复编写上面这么多代码。相比之下如DataBoundControl类和BaseDataList类都已经帮你完成了上面的工作,在有选择的情况下,我们当然不愿意写上面这么多的代码。所以说上面的这堆代码也只供你参考,能够使用新的基类的话,尽量使用,如果真的需要这么做的话,你就需要这么去改你的数据绑定控件。

    这篇可能讲的不是很详细,大家如果真的有必要这么做的话,可以仔细看看。不足之处还请大家纠正^_^.
    晚了,睡觉去了。
  • 相关阅读:
    ELM学习
    《进化》从孤胆极客到高效团队
    《人件》《PeopleWare》 【美】Tom DeMarco TimothyLister 著 肖然 张逸 滕云 译
    《进化》从孤胆极客到高效团队---Notes1
    大数据第一部分LInux学习Note1
    C#Windows窗体初学
    C#初学笔记(Windows编程的基本概念)
    C#学习2017-9-26(读取文本文件和读取二进制文件)Notes9
    C#学习2017-9-26Notes8(文件和流,FileStream类)
    C#学习笔记Notes8(接口,接口实现,程序集,命名空间,using)
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/675271.html
Copyright © 2011-2022 走看看