zoukankan      html  css  js  c++  java
  • SwitchPartManager:在UpdatePanel中灵活地切换不同用户控件

      这是一个很常见的使用场景,尤其是出现了UpdatePanel之后:页面中有一排菜单,点击菜单中的每一项,都会使某个UpdatePanel中出现不同的控制面板。在开发时,往往会将每个的控制面板写成不同的用户控件,点击菜单时事实上就是在UpdatePanel中放入不同的用户控件。

      如果要开发这样的功能,从理论上来说并不困难,但是如果要能够在控件之间灵活切换,甚至要从控件A的某个操作中切换到控件B,可能就需要增加控件之间的耦合度了。因此,如何控制这样的切换似乎需要细细考虑一下。

      在这里,我选择使用一个第三方的控件来进行统一处理,这个控件就是SwitchPartManager。在了解这个控件的实现之前,我们先来看一下一个简单的使用示例吧。

     

    使用效果

      首先,在页面中,会使用两个按钮在两个用户控件之间进行切换。在SwitchPartManager的PlaceHolderUpdatePanelID属性指定了作为容器的UpdatePanel,而点击不同的按钮,则会调用ScriptManager的SwitchTo方法切换至不同的控件。如下:

    Default.aspx
    <jeffz:SwitchPartManager ID="SwitchPartManager1" runat="server"
        PlaceHolderUpdatePanelID="UpdatePanel1" />
    
    <asp:Button ID="ButtonA" runat="server" Text="ControlA" OnClick="ButtonA_Click" />
    <asp:Button ID="ButtonB" runat="server" Text="ControlB" OnClick="ButtonB_Click" />
    
    <hr />
    
    <asp:UpdatePanel ID="UpdatePanel1" runat="server"></asp:UpdatePanel>
    Default.aspx.cs
    protected void Page_Load(object sender, EventArgs e)
    {
        ScriptManager sm = ScriptManager.GetCurrent(this);
        sm.RegisterAsyncPostBackControl(this.ButtonA);
        sm.RegisterAsyncPostBackControl(this.ButtonB);
    }
    
    protected void ButtonA_Click(object sender, EventArgs e)
    {
        SwitchPartManager.GetCurrent(this).SwitchTo("ControlA");
    }
    
    protected void ButtonB_Click(object sender, EventArgs e)
    {
        SwitchPartManager.GetCurrent(this).SwitchTo("ControlB");
    }

     

      在ControlA中有一个按钮,点击它之后将会切换到ControlB。如下:

    ControlA.ascx
    This is Control A. 
    <asp:LinkButton ID="LinkButton1" runat="server"
        OnClick="LinkButton1_Click">Switch To Control B</asp:LinkButton>
    ControlA.ascx.cs
    protected void LinkButton1_Click(object sender, EventArgs e)
    {
        SwitchPartManager.GetCurrent(this.Page).SwitchTo("ControlB");
    }

     

      而在ControlB中,它自身含有一个UpdatePanel和一个按钮,点击按钮则可以刷新时间:

    ControlB.ascx
    This is Control B
    <br />
    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
        <ContentTemplate>
            <%= DateTime.Now %>
            <asp:Button ID="Button1" runat="server" Text="Refresh Time" />
        </ContentTemplate>
    </asp:UpdatePanel>

     

      编写代码,控件之间的切换都是非常的容易。大家可以点击这里查看使用效果。

     

    SwitchPartManager控件实现

      实现这么一个控件其实比想象中容易许多。处理这个问题的关键在于如何在(同步或异步)PostBack后正确地恢复当前已经加载的控件。只要能够正确恢复了控件的状态,剩下的问题都是由ASP.NET自身的机制来完成了,例如触发事件等等。

      我们来看一下SwitchPartManager的关键实现代码:

    SwitchPartManager关键代码
    [PersistChildren(false)]
    [ParseChildren(true)]
    [NonVisualControl]
    public class SwitchPartManager : Control
    {
        private const string HiddenElementName = "__PartType__";
    
        private bool initialized = false;
    
        private string partTypeToSave = null;
    
        public static SwitchPartManager GetCurrent(Page page)
        {
            return page.Items[typeof(SwitchPartManager)] as SwitchPartManager;
        }
    
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
    
            if (this.Page.Items.Contains(typeof(SwitchPartManager)))
            {
                throw new InvalidOperationException("One SwitchPartManager per page.");
            }
    
            this.Page.Items[typeof(SwitchPartManager)] = this;
    
            this.Page.InitComplete += new EventHandler(Page_InitComplete);
            this.Page.PreRenderComplete += new EventHandler(Page_PreRenderComplete);
        }
    
        private void Page_InitComplete(object sender, EventArgs e)
        {
            this.initialized = true;
    
            string partType = this.Page.Request.Params[SwitchPartManager.HiddenElementName];
            if (partType != null)
            {
                this.SwitchTo(partType);
            }
        }
    
        private void Page_PreRenderComplete(object sender, EventArgs e)
        {
            if (!String.IsNullOrEmpty(this.partTypeToSave))
            {
                ScriptManager.RegisterHiddenField(
    this.Page, SwitchPartManager.HiddenElementName, this.partTypeToSave); } } // 得到作为容器的UpdatePanel private UpdatePanel PlaceHolderUpdatePanel { get { // ... } } public void SwitchTo(string partType) { Control container = this.PlaceHolderUpdatePanel.ContentTemplateContainer; container.Controls.Clear(); Control control = this.Page.LoadControl(partType + ".ascx"); control.ID = "JustToPreserveUniqueName"; container.Controls.Add(control); this.partTypeToSave = partType; } }

     

      SwitchTo方法是用于切换用户控件的方法,它会将UpdatePanel内已有的控件(例如从ControlA切换到ControlB时,UpdatePanel中已经有了ControlA)清除,然后再向UpdatePanel中添加新的控件。

      我在这里将当前当前的控件标识记录在私有变量partTypeToSave中,它会在Page的PreRenderComplete时作为<input type="hidden" />的形式输出。我在这里使用了HiddenField作为保留控件选择状态的方式,这样可以避免因为ViewState被禁用而导致的数据丢失。

      这样,我们的页面在PostBack之后,就能够通过接受到的信息来恢复UpdatePanel的控件了。我在在Page的InitComplete时恢复UpdatePanel中的控件——很容易,直接使用SwitchTo方法就可以了。

      这几乎就是SwitchPartManager的完整代码。其实这个类相当的简单,但是它的价值却不小。但是根据我的经验,似乎为了自己的项目开发Custom Control的朋友不多,大家大都是在写用户控件(ascx)。其实在有些时候,为自己的应用编写一个Custom Control,尤其是用于“管理”的控件,其实能够使页面的逻辑变得清晰许多。

     

      点击这里下载SwitchPartManager的代码。

    转自:http://www.cnblogs.com/JeffreyZhao/archive/2007/03/29/switchpartmanager.html

  • 相关阅读:
    留言板
    移动端开发
    css3的伪类
    JQuery移除事件
    关于offset,你知道多少?
    关于section-scroll插件:
    jQuery响应式弹出层和对话框插插件magnific-popup.css
    col-lg-8 col-lg-offset-2
    关于渐变属 gradient:
    关于 window.onresize
  • 原文地址:https://www.cnblogs.com/asyuras/p/701255.html
Copyright © 2011-2022 走看看