微软的 UserControl , 感觉跟用 VB 一样 . 乍用起来,很爽, 深入下去, 很不爽.
爽就不多说了.说说不爽.
静态绑定很爽,但是大多数的时候,都需要动态绑定, 到目前为止,我发现最多,最头疼的问题也是动态绑定的机制不同,所造成的效果不同上.
protected void Page_Load(object sender, EventArgs e)
{
this.Controls.Add ( this.LoadControl("b.ascx"));
}
注意:不能添加 第一次加载的条件,那样的话,一回发, B.ascx 就会消失.
这样写,跟 静态绑定是一样的, 很爽.但,更多时候,我们需要把 UserControl 添加到容器中, 比如 Panel . 像这样:
protected void Page_Load(object sender, EventArgs e)
{
this.Panel1.Controls.Add(this.LoadControl("b.ascx"));
}
这样的话,问题是: Panel 不能保存子控件内容. 导致 回发, B.ascx 消失.
换一个方法 this.Controls.AddAt 也不行. 即使用 this.Controls.Add ( this.LoadControl("b.ascx")); , 然后,再把 B.ascx 的内容 “移” 到Panel 中,也不行。
原因是: UserControl 没有保存子控件内容。
如何做到保存子控件的内容呢? 这里要用一个控件:

Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.Web;
namespace WebCon.MySimple
{
[ToolboxData("<{0}:MyUserPanel runat=server></{0}:MyUserPanel>")]
public class MyUserPanel : Control, INamingContainer
{
public delegate void VirualPathChangedDelegate(string VirualPath);
public event VirualPathChangedDelegate VirualPathChanged;
public string _virtualPath
{
get
{
return (this.Page as WebConPage).MyVar.SysVar[this.ClientID + "_virtualPath"];
}
set
{
(this.Page as WebConPage).MyVar.SysVar[this.ClientID + "_virtualPath"] = value;
}
}
private Control _view;
public bool IsFirstLoad
{
get
{
if ((this.Page as WebConPage).MyVar.SysVar[this.ClientID + "IsFirstLoad"] == null) return true;
else return Convert.ToBoolean((this.Page as WebConPage).MyVar.SysVar[this.ClientID + "IsFirstLoad"]);
}
set
{
(this.Page as WebConPage).MyVar.SysVar[this.ClientID + "IsFirstLoad"] = value.ToString();
}
}
/// <summary>
/// 设置用户控件路径,并自动绑定.
/// </summary>
public string VirtualPath
{
get { return this._virtualPath; }
set
{
//if (string.IsNullOrEmpty(value)) return;
string oldValue = this._virtualPath;
this._virtualPath = value;
if (this.Page != null &&
(value != oldValue || string.IsNullOrEmpty(value) == true)
)
{
IsFirstLoad = true;
this.ChildControlsCreated = false;
this.EnsureChildControls();
}
if (VirualPathChanged != null)
{
VirualPathChanged(value);
}
}
}
protected override void OnPreRender(EventArgs e)
{
IsFirstLoad = false;
base.OnPreRender(e);
}
/// <summary>
/// 强制重新绑定.
/// </summary>
public virtual void Bind()
{
Bind(this.VirtualPath);
}
public virtual void Bind(string TheVirtualPath)
{
this._virtualPath = TheVirtualPath;
IsFirstLoad = true;
CreateChildControls();
}
/// <summary>
/// 额外信息.用于传值. 通过 Url Search 的方式.
/// </summary>
public string Value
{
get
{
if (string.IsNullOrEmpty(this.VirtualPath) == true || this.VirtualPath.Contains("|") == false) return string.Empty;
return this.VirtualPath.Substring(this.VirtualPath.IndexOf("|") + 1);
}
}
/// <summary>
/// 取得存放 UserControl 的控件.
/// </summary>
public Control View
{
get { return this._view; }
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (!string.IsNullOrEmpty(this.VirtualPath))
{
this.EnsureChildControls();
}
}
protected override void CreateChildControls()
{
this.Controls.Clear();
if (string.IsNullOrEmpty(this.VirtualPath))
{
this.ClearChildState();
return;
}
if (this.Page == null)
{
throw new Exception("ViewPanel.Page is null.");
}
string strPath = this.VirtualPath.Split('|')[0];
if (string.IsNullOrEmpty(strPath)) return;
if (string.IsNullOrEmpty(strPath) == false)
{
this._view = this.Page.LoadControl(strPath);
}
if (this._view == null)
{
return;
}
this._view.ID = "ucView_" + this.ClientID;
this.ClearChildState();
this.Controls.Add(this._view);
}
protected override object SaveViewState()
{
return new Pair(base.SaveViewState(), this.VirtualPath);
}
protected override void LoadViewState(object savedState)
{
Pair pair = savedState as Pair;
if (pair != null)
{
base.LoadViewState(pair.First);
this._virtualPath = pair.Second as string;
}
}
}
}
即使如此, 在回发的时候,服务器端依然有丢失数据的时候。如下:
自己封装的双列表 MyGridList2(两个GridView),其中主List更新操作,在页面上运行良好,切换到 UserControl 上,更新的话,找不到 行数据。
基本上, UserControl 算是个半成品。 慎用! 如果需要复杂应用,可以改用 WebContro l!!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端