#asp.net #webforms
#asp.net #веб-формы
Вопрос:
Дан сценарий, в котором страница / элемент управления должен отображать разные представления (например, вкладки) в разных обстоятельствах (аргумент строки запроса, обратная передача из элемента управления, пользовательские настройки, извлеченные из базы данных) Обычно я бы поместил элемент управления типа MultiView или Placeholder и переключил активный индекс представления или свойство Visible следующим образом:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm2.aspx.cs" Inherits="TestWebApplication.WebForm2" %>
<%@ Register Src="SomeControl.ascx" TagName="SomeControl" TagPrefix="uc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:PlaceHolder runat="server" ID="phControl" Visible="false">
<uc1:SomeControl ID="SomeControl1" runat="server" />
</asp:PlaceHolder>
<asp:PlaceHolder runat="server" ID="phNotControl" Visible="false">
Some other content
</asp:PlaceHolder>
</div>
</form>
</body>
</html>
И я бы переключал представления в коде в зависимости от логики, подобной этой:
using System;
namespace TestWebApplication
{
public partial class WebForm2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
phControl.Visible = false;
phNotControl.Visible = true;
}
}
}
Это элемент управления:
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="SomeControl.ascx.cs" Inherits="TestWebApplication.SomeControl" EnableViewState="false" %>
I am the control
И код, лежащий в основе элемента управления:
using System;
namespace TestWebApplication
{
public partial class SomeControl : System.Web.UI.UserControl
{
protected void Page_Init(object sender, EventArgs e)
{
Response.Write("I am the control's Init and I am executing heavy operations <br />");
}
protected void Page_Load(object sender, EventArgs e)
{
Response.Write("I am the control's Load <br />");
}
protected void Page_PreRender(object sender, EventArgs e)
{
Response.Write("I am the control's PreRender and I am only called if the control is Visible <br />");
}
}
}
Однако что, если рассматриваемому элементу управления предстоит выполнить некоторую относительно тяжелую работу (вызов базы данных) в своих событиях инициализации и загрузки? Они выполняются, даже если элемент управления не виден, и замедляют работу страницы. Одним из возможных решений, которое я вижу, является перенос всей работы в метод PreRender дочернего элемента управления, поскольку он не выполняется для элементов управления, которые не видны. Однако это не сработает, если элемент управления принимает пользовательский ввод от некоторого динамически заполняемого элемента управления (например, dropdownlist), потому что логика, которая заполняет выпадающий список параметрами, не будет выполнена.
Я предложил следующие решения:
-
Перенесите тяжелую работу в метод предварительной обработки и оберните ее в if (!IsPostBack). Затем пусть ViewState содержит возможные значения для выпадающего списка и ASP.NET восстановит его. Недостатком является то, что он использует ViewState и увеличивает размер страницы.
-
Создайте элемент управления динамически с помощью LoadControl и добавьте его в заполнитель из исходного кода. Это вызовет события догоняющего доступа, и код, который заполняет выпадающий список, может быть помещен в метод Init, которому он принадлежит. Недостатком является то, что макет определен в исходном коде. Глядя на разметку, невозможно увидеть, какие элементы управления находятся на странице, а глядя на код, стоящий за ней, неясно, где появится элемент управления. Это также усложняет стилизацию и другие операции «проектирования».
-
Оставьте все как есть. Недостатком является то, что будут дополнительные запросы к базе данных, и если будет много представлений, они будут суммироваться.
Мой актуальный вопрос заключается в том, как я решаю эту проблему, не помещая материал в ViewState, без нескольких запросов и без перетаскивания моего макета в код позади.
Ответ №1:
Может ли это быть решением для выполнения вызова AJAX для вашей тяжелой работы с базой данных?
Затем вы могли бы отобразить представление и в фоновом режиме загрузить нужные вам данные и отобразить их. Страница загружалась бы очень быстро, и вы могли бы отобразить некоторое указание на то, что данные в данный момент загружаются.
Комментарии:
1. Да, но это был не тот ответ, который я искал. Прежде всего, это равносильно динамическому созданию элемента управления в C #, за исключением того, что вы создаете его в JS. Вы все еще не можете четко видеть поток в ASP.NET разметка. Во-вторых, что, если я по какой-то причине не хочу делать это с помощью AJAX (например, SEO или какой-либо мобильный просмотр) Спасибо за ответ.
Ответ №2:
Как насчет создания общедоступного метода в ваших пользовательских элементах управления, такого как InitControl(). Выполняйте всю тяжелую работу в InitControl () вместо этого при загрузке страницы. Затем, на родительской странице, когда страница отображается, вызовите InitControl .
using System;
namespace TestWebApplication
{
public partial class WebForm2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
phControl.Visible = false;
phNotControl.Visible = true;
SomeControl1.InitControl();
}
}
}
Не выполняйте никакой работы в событии OnLoad ваших пользовательских элементов управления.