UpdatePanel内にプログラムでユーザーコントロールを追加する
-
03-07-2019 - |
質問
部分的にポストバックする更新パネル内にコントロールを動的に追加するのに問題があります。動的コントロールに関する多くの記事を読んでおり、ポストバックでそれらを追加および管理する方法を理解していますが、その情報のほとんどは適用されず、部分的なポストバックでは機能しません。 UpdatePanelsでそれらを追加および保守するための有用な情報が見つかりません。可能であれば、Webサービスを作成せずにこれを実行したいと思います。誰かが役に立つ情報へのアイデアや参照を持っていますか?
解決
これは、asp.netプログラマーにとってよくある落とし穴の1つですが、実際に何が起こっているかを把握しているときに正しくするのはそれほど難しくありません(常にビューステートを記憶してください!)。
次のコードは、物事を行う方法を説明しています。ユーザーがメニューをクリックして、updatepanel内のページにユーザーコントロールを追加するアクションをトリガーできるシンプルなページです。
(このコードは、ここから借りています、およびこのトピックに関する多くの情報があります)
<%@ 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>
and
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();
}
}
コードビハインド用。
それは基本的にそれです。ユーザーがメニュー項目をクリックすると、コントロール自体がページに動的に追加される間(updatePanel内(実際にはupdatePanel内のplaceHolder内))、ビューステートが LastLoadedControl で保持されていることがはっきりとわかります。 、サーバーに非同期ポストバックを送信します。
詳細についてはこちらもご覧ください:
- http://aspnet.4guysfromrolla.com/articles/081402-1.aspx
- http://aspnet.4guysfromrolla.com/articles/082102-1.aspx
そしてもちろんウェブサイトサンプルコードを保持していますここで使用しました。
他のヒント
上記のメソッドを使用すると、イベントを処理するときにLoadUserControl()が2回呼び出されるという問題が発生しました。他の記事をいくつか読んだので、私の修正を示したいと思います。
1)Page_Loadの代わりにLoadViewstateを使用して、ユーザーコントロールをロードします。
protected override void LoadViewState(object savedState)
{
base.LoadViewState(savedState);
if (!string.IsNullOrEmpty(CurrentUserControl))
LoadDataTypeEditorControl(CurrentUserControl, panelFVE);
}
2)ユーザーコントロールの読み込み時にコントロールIDを設定することを忘れないでください:
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;
}
これを試してください:
Literal literal = new Literal();
literal.Text = "<script type='text/javascript' src='http://www.googleadservices.com/pagead/conversion.js'>";
UpdatePanel1.ContentTemplateContainer.Controls.Add(literal);
リテラルのコンテンツを任意のHTMLコンテンツに置き換えることができます...