Я спросил как отрендерить HTML-код UserControl и получил код, работающий для динамически сгенерированного UserControl.
Теперь я пытаюсь использовать LoadControl для загрузки ранее созданного элемента управления и вывода его HTML-кода, но он дает мне следующее:
Элемент управления типа TextBox должен быть помещен в тег формы с runat = server.
На самом деле я не добавляю элемент управления на страницу, я просто пытаюсь получить его HTML-код. Есть идеи?
Вот код, с которым я играю:
TextWriter myTextWriter = new StringWriter();
HtmlTextWriter myWriter = new HtmlTextWriter(myTextWriter);
UserControl myControl = (UserControl)LoadControl("newUserControl.ascx");
myControl.RenderControl(myWriter);
return myTextWriter.ToString();





Вы можете добавить форму в свой пользовательский элемент управления или использовать обычное поле ввода html.
<input type = "text" />
Обновлено: если вы пытаетесь сделать что-то AJAXy, возможно, вам нужно что-то вроде этого http://aspadvice.com/blogs/ssmith/archive/2007/10/19/Render-User-Control-as-String-Template.aspx
public static string RenderView<D>(string path, D dataToBind)
{
Page pageHolder = new Page();
UserControl viewControl = (UserControl) pageHolder.LoadControl(path);
if (viewControl is IRenderable<D>)
{
if (dataToBind != null)
{
((IRenderable<D>) viewControl).PopulateData(dataToBind);
}
}
pageHolder.Controls.Add(viewControl);
StringWriter output = new StringWriter();
HttpContext.Current.Server.Execute(pageHolder, output, false);
return output.ToString();
}
При необходимости вы можете удалить часть привязки данных.
Я подумал о добавлении второго UserControl с тем же представлением, за исключением runat = "server" для каждого элемента управления, но это определенно не DRY и накладывает множество ограничений на такие вещи, как раскрывающиеся списки.
Проблема заключается в отсутствии формы, ваши раскрывающиеся списки не смогут взаимодействовать с сервером, лучше всего обернуть содержимое пользовательского элемента управления с помощью <form runat = "server">
У меня есть <form runat = "server"> вокруг всей моей страницы, но этот элемент управления не видит этого, я думаю. Вы все еще рекомендовали бы это?
На самом деле я просто добавляю этот элемент управления на страницу, но у меня возникают проблемы, когда я пытаюсь использовать RenderControl () Control. Есть ли проблема с тем, как я захватываю текст?
Заключение пользовательского элемента управления в тег формы приводит к ошибке. (На странице может быть только один серверный тег формы.)
Вы можете добавить элемент управления на страницу, отобразить html, а затем удалить элемент управления со страницы.
Или попробуйте это:
Page tmpPage = new TempPage(); // temporary page
Control tmpCtl = tmpPage.LoadControl( "~/UDynamicLogin.ascx" );
//the Form is null that's throws an exception
tmpPage.Form.Controls.Add( tmpCtl );
StringBuilder html = new StringBuilder();
using ( System.IO.StringWriter swr = new System.IO.StringWriter( html ) ) {
using ( HtmlTextWriter writer = new HtmlTextWriter( swr ) ) {
tmpPage.RenderControl( writer );
}
}
Я действительно пытался добавить его на страницу, но позвольте мне попробовать, что вы там делаете.
Это говорит о том, что у меня нет доступа к tmpForm в этом контексте. (Также TempPage должна быть страницей, верно?)
Ой, там должна быть tmpPage.
Это грязное решение, которое я использовал на данный момент (заставьте его работать, тогда исправьте, верно?).
Я уже создал новый класс, который наследует класс UserControl и от которого были унаследованы все остальные созданные мной «UserControls». Я назвал его formPartial (кивок в сторону Rails), и он находится внутри метода общедоступной строки renderMyHTML ():
TextWriter myTextWriter = new StringWriter();
HtmlTextWriter myWriter = new HtmlTextWriter(myTextWriter);
UserControl myDuplicate = new UserControl();
TextBox blankTextBox;
foreach (Control tmpControl in this.Controls)
{
switch (tmpControl.GetType().ToString())
{
case "System.Web.UI.LiteralControl":
blankLiteral = new LiteralControl();
blankLiteral.Text = ((LiteralControl)tmpControl).Text;
myDuplicate.Controls.Add(blankLiteral);
break;
case "System.Web.UI.WebControls.TextBox":
blankTextBox = new TextBox();
blankTextBox.ID = ((TextBox)tmpControl).ID;
blankTextBox.Text = ((TextBox)tmpControl).Text;
myDuplicate.Controls.Add(blankTextBox);
break;
// ...other types of controls (ddls, checkboxes, etc.)
}
}
myDuplicate.RenderControl(myWriter);
return myTextWriter.ToString();
Недостатки с головы до ног:
Было бы легко испортить 1 или 2. Надеюсь, это поможет кому-то другому придумать более элегантное решение.
В качестве альтернативы вы можете отключить проверку ServerForm / Event на странице, которая отображает элемент управления в строку.
В следующем примере показано, как это сделать.
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string rawHtml = RenderUserControlToString();
}
private string RenderUserControlToString()
{
UserControl myControl = (UserControl)LoadControl("WebUserControl1.ascx");
using (TextWriter myTextWriter = new StringWriter())
using (HtmlTextWriter myWriter = new HtmlTextWriter(myTextWriter))
{
myControl.RenderControl(myWriter);
return myTextWriter.ToString();
}
}
public override void VerifyRenderingInServerForm(Control control)
{ /* Do nothing */ }
public override bool EnableEventValidation
{
get { return false; }
set { /* Do nothing */}
}
}
К сожалению, вам нужно переопределить его для всей страницы, но у меня это сработало. Хороший.
Да, это не красиво, но легко. Я думаю, вы могли бы ввести логическую переменную класса и использовать ее для включения и выключения "отключения". Таким образом, вы можете просто временно отключить его во время рендеринга элемента управления, а затем снова включить для остальной части страницы. Стоит попробовать, если он вам нужен.
У меня была такая же проблема с использованием кода, аналогичного @TcKs, и я не смог заставить ни один из этих примеров работать для меня. Я заставил его работать, используя метод LoadControl для UserControl как таковой:
UserControl uc = new UserControl();
Control c = uc.LoadControl("newUserControl.ascx");
c.RenderControl(myWriter);
Этого не происходит, когда я удаляю runat = "server" из элементов управления в UserControl.