您的位置:首页 > 其它

SwitchPartManager:在UpdatePanel中灵活地切换不同用户控件

2016-07-29 00:00 423 查看
这是一个很常见的使用场景,尤其是出现了UpdatePanel之后:页面中有一排菜单,点击菜单中的每一项,都会使某个UpdatePanel中出现不同的控制面板。在开发时,往往会将每个的控制面板写成不同的用户控件,点击菜单时事实上就是在UpdatePanel中放入不同的用户控件。
如果要开发这样的功能,从理论上来说并不困难,但是如果要能够在控件之间灵活切换,甚至要从控件A的某个操作中切换到控件B,可能就需要增加控件之间的耦合度了。因此,如何控制这样的切换似乎需要细细考虑一下。
在这里,我选择使用一个第三方的控件来进行统一处理,这个控件就是SwitchPartManager。在了解这个控件的实现之前,我们先来看一下一个简单的使用示例吧。

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

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。如下:
This is Control A.
<asp:LinkButton ID="LinkButton1" runat="server"
OnClick="LinkButton1_Click">Switch To Control B</asp:LinkButton>

protected void LinkButton1_Click(object sender, EventArgs e)
{
SwitchPartManager.GetCurrent(this.Page).SwitchTo("ControlB");
}


而在ControlB中,它自身含有一个UpdatePanel和一个按钮,点击按钮则可以刷新时间:
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的关键实现代码:
[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的代码。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: