如何呈现 WebUserControl 客户端
How to render a WebUserControl client-side
我创建了一个 Web 用户控件,其中包含一些 ASP.NET 和第三方控件。
我已经在页面标记中测试了我的控件,它运行良好。
<APP:MyControl ID="myControl1" InitializeWithValue="Employee" />
<APP:MyControl ID="myControl2" InitializeWithValue="Supplier" />
现在,我想在同一个页面中呈现此控件,而不是在页面首次呈现时呈现。事实上,我将单击一个将调用回调的按钮,在那一刻我想呈现控件。
我正在尝试做这样的事情。
void ICallbackEventHandler.RaiseCallbackEvent(string eventArgument)
{
MyControl c1 = new MyControl();
c1.InitializeWithValue = Person.Enum.Employee; //<--CRASH
System.Text.StringBuilder sb = new System.Text.StringBuilder();
System.IO.StringWriter sw = new System.IO.StringWriter(sb);
HtmlTextWriter hw = new HtmlTextWriter(sw);
c1.RenderControl(hw);
return sb.ToString();
}
然后在我的客户端接收器上
<a href="javascript:void(0);" onclick="testcallback('', '')">Test</a>
<div id="divControls"></div>
<script>
function receiver(arguments, context) {
document.getElementById('divControls').innerHTML = arguments;
}
</script>
但是在初始化的时候就崩溃了,因为WebUserControl内部的所有控件都是null。它们还没有被初始化。
这是控件的属性
[Browsable(true)]
public Person.Enum InitializeWithValue
{
get { return this.enumPersonValue; }
set
{
this.enumPersonValue = value;
//Literal control
this.litPersonType.Text = "Employee"; //<-- CRASH because litPersonType is null.
}
}
有些人可以帮助我更正此问题或建议我另一种呈现 Web 控件但在客户端的方式?
用户控件通常与页面生命周期紧密相关,因此您需要重新创建整个页面并呈现它。
其次,您应该使用它的 .ascx 文件加载您的用户控件,而不仅仅是它的 class,这是必需的,因为只有您的 class 是不够的。
您仍然可以尝试像只创建但使用 Page.LoadControl
:
void ICallbackEventHandler.RaiseCallbackEvent(string eventArgument)
{
MyControl c1 = (MyControl)page.LoadControl("/Controls/myControl.ascx");
c1.InitializeWithValue = Person.Enum.Employee; //<--CRASH
System.Text.StringBuilder sb = new System.Text.StringBuilder();
System.IO.StringWriter sw = new System.IO.StringWriter(sb);
HtmlTextWriter hw = new HtmlTextWriter(sw);
c1.RenderControl(hw);
return sb.ToString();
}
但是如果您的控件具有与页面生命周期相关的事件,您可能需要为其创建一个完整的上下文:
你可以这样做:
using (var stringWriter = new StringWriter())
{
using (var page = new Page())
{
MyControl myControl = (MyControl)page.LoadControl("/Controls/myControl.ascx");
var head = new HtmlHead();
page.Controls.Add(head);
var form = new HtmlForm();
page.Controls.Add(form);
var div = new HtmlGenericControl("div");
div.ID = "myControlContent";
form.Controls.Add(div);
div.Controls.Add(myControl);
HttpContext.Current.Server.Execute(page, stringWriter, false);
}
return stringWriter.ToString()
}
然后在你的JS中你可以解析整个html并只得到div#myControlContent
的innerHTML,例如:
function receiver(arguments, context) {
var parser = new DOMParser();
var doc = parser.parseFromString(arguments, "text/html");
document.getElementById('divControls').innerHTML = doc.getElementById('myControlContent').innerHTML;
}
请注意 DOMParser
仅在现代浏览器中可用,但您可以找到适用于旧版浏览器的其他方法...
我创建了一个 Web 用户控件,其中包含一些 ASP.NET 和第三方控件。
我已经在页面标记中测试了我的控件,它运行良好。
<APP:MyControl ID="myControl1" InitializeWithValue="Employee" />
<APP:MyControl ID="myControl2" InitializeWithValue="Supplier" />
现在,我想在同一个页面中呈现此控件,而不是在页面首次呈现时呈现。事实上,我将单击一个将调用回调的按钮,在那一刻我想呈现控件。
我正在尝试做这样的事情。
void ICallbackEventHandler.RaiseCallbackEvent(string eventArgument)
{
MyControl c1 = new MyControl();
c1.InitializeWithValue = Person.Enum.Employee; //<--CRASH
System.Text.StringBuilder sb = new System.Text.StringBuilder();
System.IO.StringWriter sw = new System.IO.StringWriter(sb);
HtmlTextWriter hw = new HtmlTextWriter(sw);
c1.RenderControl(hw);
return sb.ToString();
}
然后在我的客户端接收器上
<a href="javascript:void(0);" onclick="testcallback('', '')">Test</a>
<div id="divControls"></div>
<script>
function receiver(arguments, context) {
document.getElementById('divControls').innerHTML = arguments;
}
</script>
但是在初始化的时候就崩溃了,因为WebUserControl内部的所有控件都是null。它们还没有被初始化。
这是控件的属性
[Browsable(true)]
public Person.Enum InitializeWithValue
{
get { return this.enumPersonValue; }
set
{
this.enumPersonValue = value;
//Literal control
this.litPersonType.Text = "Employee"; //<-- CRASH because litPersonType is null.
}
}
有些人可以帮助我更正此问题或建议我另一种呈现 Web 控件但在客户端的方式?
用户控件通常与页面生命周期紧密相关,因此您需要重新创建整个页面并呈现它。
其次,您应该使用它的 .ascx 文件加载您的用户控件,而不仅仅是它的 class,这是必需的,因为只有您的 class 是不够的。
您仍然可以尝试像只创建但使用 Page.LoadControl
:
void ICallbackEventHandler.RaiseCallbackEvent(string eventArgument)
{
MyControl c1 = (MyControl)page.LoadControl("/Controls/myControl.ascx");
c1.InitializeWithValue = Person.Enum.Employee; //<--CRASH
System.Text.StringBuilder sb = new System.Text.StringBuilder();
System.IO.StringWriter sw = new System.IO.StringWriter(sb);
HtmlTextWriter hw = new HtmlTextWriter(sw);
c1.RenderControl(hw);
return sb.ToString();
}
但是如果您的控件具有与页面生命周期相关的事件,您可能需要为其创建一个完整的上下文:
你可以这样做:
using (var stringWriter = new StringWriter())
{
using (var page = new Page())
{
MyControl myControl = (MyControl)page.LoadControl("/Controls/myControl.ascx");
var head = new HtmlHead();
page.Controls.Add(head);
var form = new HtmlForm();
page.Controls.Add(form);
var div = new HtmlGenericControl("div");
div.ID = "myControlContent";
form.Controls.Add(div);
div.Controls.Add(myControl);
HttpContext.Current.Server.Execute(page, stringWriter, false);
}
return stringWriter.ToString()
}
然后在你的JS中你可以解析整个html并只得到div#myControlContent
的innerHTML,例如:
function receiver(arguments, context) {
var parser = new DOMParser();
var doc = parser.parseFromString(arguments, "text/html");
document.getElementById('divControls').innerHTML = doc.getElementById('myControlContent').innerHTML;
}
请注意 DOMParser
仅在现代浏览器中可用,但您可以找到适用于旧版浏览器的其他方法...