Программное добавление элементов управления пользователя внутри UpdatePanel

У меня возникают проблемы с динамическим добавлением элементов управления внутри панели обновлений с частичной обратной обработкой. Я прочитал много статей по динамическим элементам управления, и я понимаю, как добавлять и поддерживать их с помощью обратных передач, но большая часть этой информации не применяется и не будет работать для частичных обратных передач. Я не могу найти полезную информацию о добавлении и обслуживании с помощью UpdatePanels. Я бы хотел сделать это без создания веб-службы, если это возможно. Есть ли у кого-нибудь идеи или ссылки на полезную информацию?

Ответы

Ответ 1

Это, я думаю, одна из распространенных ошибок для программистов asp.net, но на самом деле это трудно понять, когда вы знаете, что происходит (всегда помните о своем представлении!).

следующий фрагмент кода объясняет, как это можно сделать. Это простая страница, на которой пользователь может щелкнуть по меню, которое вызовет действие, которое добавит элемент управления пользователя на страницу внутри панели обновления.
(Этот код заимствован отсюда, и у него есть много информации об этой теме)

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="SampleMenu1.aspx.cs" Inherits="SampleMenuPage1" %>
<!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>Sample Menu</title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:Menu ID="Menu1" runat="server" OnMenuItemClick="Menu1_MenuItemClick">
            <Items>
                <asp:MenuItem Text="File">
                    <asp:MenuItem Text="Load Control1"></asp:MenuItem>
                    <asp:MenuItem Text="Load Control2"></asp:MenuItem>
                    <asp:MenuItem Text="Load Control3"></asp:MenuItem>
                </asp:MenuItem>
            </Items>
        </asp:Menu>
        <br />
        <br />
        <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
        <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
            <ContentTemplate>
                <asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
            </ContentTemplate>
            <Triggers>
                <asp:AsyncPostBackTrigger ControlID="Menu1" />
            </Triggers>
        </asp:UpdatePanel>
    </form>
</body>
</html>

и

using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class PlainSampleMenuPage : System.Web.UI.Page
{
    private const string BASE_PATH = "~/DynamicControlLoading/";

    private string LastLoadedControl
    {
        get
        {
            return ViewState["LastLoaded"] as string;
        }
        set
        {
            ViewState["LastLoaded"] = value;
        }
    }

    private void LoadUserControl()
    {
        string controlPath = LastLoadedControl;

        if (!string.IsNullOrEmpty(controlPath))
        {
            PlaceHolder1.Controls.Clear();
            UserControl uc = (UserControl)LoadControl(controlPath);
            PlaceHolder1.Controls.Add(uc);
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        LoadUserControl();
    }

    protected void Menu1_MenuItemClick(object sender, MenuEventArgs e)
    {
        MenuItem menu = e.Item;

        string controlPath = string.Empty;

        switch (menu.Text)
        {
            case "Load Control2":
                controlPath = BASE_PATH + "SampleControl2.ascx";
                break;
            case "Load Control3":
                controlPath = BASE_PATH + "SampleControl3.ascx";
                break;
            default:
                controlPath = BASE_PATH + "SampleControl1.ascx";
                break;
        }

        LastLoadedControl = controlPath;
        LoadUserControl();
    }
}

для кода позади.

Это в основном это. Вы можете ясно видеть, что viewstate хранится в LastLoadedControl, в то время как сами элементы управления динамически добавляются на страницу (внутри updatePanel (на самом деле внутри placeHolder внутри updatePanel), когда пользователь нажимает на элемент меню, который будет отправлять асинхронную обратную передачу на сервер.

Более подробную информацию можно найти здесь:

и, конечно, на на веб-сайте, который содержит пример кода. Я использовал здесь.

Ответ 2

Я столкнулся с проблемой, что, используя упомянутый выше метод, LoadUserControl() вызывается дважды при обработке события. Я прочитал некоторые другие статьи и хотел бы показать вам мою модификацию:

1) Используйте LoadViewstate вместо Page_Load для загрузки пользовательского элемента управления:

protected override void LoadViewState(object savedState)
{
    base.LoadViewState(savedState);

    if (!string.IsNullOrEmpty(CurrentUserControl))
        LoadDataTypeEditorControl(CurrentUserControl, panelFVE);
}

2) Не забудьте установить управляющий идентификатор при загрузке usercontrol:

private void LoadDataTypeEditorControl(string userControlName, Control containerControl)
{
    using (UserControl myControl = (UserControl) LoadControl(userControlName))
    {
        containerControl.Controls.Clear();

        string userControlID = userControlName.Split('.')[0];
        myControl.ID = userControlID.Replace("/", "").Replace("~", "");
        containerControl.Controls.Add(myControl);
    }
    this.CurrentUserControl = userControlName;
}

Ответ 3

Попробуйте следующее:

Literal literal = new Literal();
literal.Text = "<script type='text/javascript' src='http://www.googleadservices.com/pagead/conversion.js'>";
UpdatePanel1.ContentTemplateContainer.Controls.Add(literal);

Вы можете заменить содержимое литерала любым содержимым HTML...