12

I have a button control. On click of this button I need to add a Link Button dynamically. The Link Button needs an event handler. Hence the dynamic Link button is first added in the Page_Load and cleared and added again in the button click handler. Please read Dynamic Control’s Event Handler’s Working for understanding the business requirement for this.

I have read On postback, how can I check which control cause postback in Page_Init event for identifying the control that caused the postback (inside Page_Load). But it is not working for my scenario.

What change need to be done to confirm whether the postback was caused by link button (inside Page_Load)?

Note: Refer the following for another scenario where it is inevitable https://codereview.stackexchange.com/questions/20510/custom-paging-in-asp-net-web-application

Note 1: I need to get the postback control ID as the first step inside if (Page.IsPostBack). I need to add the dynamic link buttons control only if it is a postback from the button or the link button. There will be other controls that causes postback. For such postbacks we should not execute this code.

Note 2: I am getting empty string for Request["__EVENTARGUMENT"] in the Page_Load

Related Question: By what event, the dynamic controls will be available in the Page (for using in FindControl). @Tung says - "Your GetPostBackControlId method is properly getting the name of the control that caused the postback, but it is unable to find a control with that id through page.FindControl because the linkbutton has not been created yet, and so page does not know of its existence. "

ASPX

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="PostbackTest.aspx.cs" Inherits="PostbackTest"
MasterPageFile="~/TestMasterPage.master" %>

<asp:Content ID="myContent" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<div id="holder" runat="server">
</div>
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="TestClick" />
</asp:Content>

CODE BEHIND

public partial class PostbackTest : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{

    if(Page.IsPostBack)
    {
        string IDValue = GetPostBackControlId(this.Page);
        int x = 0;

        holder.Controls.Clear();
        LinkButton lnkDynamic = new LinkButton();
        lnkDynamic.Click += new EventHandler(LinkClick);
        lnkDynamic.ID = "lnkDynamic123";
        lnkDynamic.Text = "lnkDynamic123";
        holder.Controls.Add(lnkDynamic);
    }
}

protected void TestClick(object sender, EventArgs e)
{
    holder.Controls.Clear();
    LinkButton lnkDynamic = new LinkButton();
    lnkDynamic.Click += new EventHandler(LinkClick);
    lnkDynamic.ID = "lnkDynamic123";
    lnkDynamic.Text = "lnkDynamic123";
    holder.Controls.Add(lnkDynamic);
}

protected void LinkClick(object sender, EventArgs e)
{

}

public static string GetPostBackControlId(Page page)
{
    if (!page.IsPostBack)
    {
        return string.Empty;
    }

    Control control = null;

    // First check the "__EVENTTARGET" for  controls with "_doPostBack" function
    string controlName = page.Request.Params["__EVENTTARGET"];
    if (!String.IsNullOrEmpty(controlName))
    {
        control = page.FindControl(controlName);
    }
    else
    {
        // if __EVENTTARGET is null, the control is a button type 
        string controlId;
        Control foundControl;

        foreach (string ctl in page.Request.Form)
        {
            // Handle ImageButton they having an additional "quasi-property" in their Id which identifies mouse x and y coordinates
            if (ctl.EndsWith(".x") || ctl.EndsWith(".y"))
            {
                controlId = ctl.Substring(0, ctl.Length - 2);
                foundControl = page.FindControl(controlId);
            }
            else
            {
                foundControl = page.FindControl(ctl);
            }

            if (!(foundControl is Button || foundControl is ImageButton)) continue;

            control = foundControl;
            break;
        }
    }

    return control == null ? String.Empty : control.ID;
}
}

REFERENCE

  1. On postback, how can I check which control cause postback in Page_Init event
  2. Dynamic Control’s Event Handler’s Working
  3. Understanding the JavaScript __doPostBack Function
  4. Access JavaScript variables on PostBack using ASP.NET Code
  5. How does ASP.NET know which event to fire during a postback?
  6. how to remove 'name' attribute from server controls?
  7. How to use __doPostBack()
4

4 に答える 4

8

asp.net でのポストバックは、Java スクリプト関数 __doPostback(source, parameter) によって行われます。

あなたの場合、それは

    __doPostback("lnkDynamic123","") something like this

したがって、コードビハインドで次のことを行います

    var btnTrigger = Request["__EVENTTARGET"]; 

     if(btnTrigger=="lnkDynamic123") 
{
}

--- これは、ポストバックの原因がリンクボタンであることを示します

于 2013-01-23T23:38:36.420 に答える
4

LinkBut​​tonがページに追加された、GetPostBackControlIdメソッドへの呼び出しを移動できます。

protected void Page_Load(object sender, EventArgs e)
{
    if (Page.IsPostBack)
    {
        holder.Controls.Clear();
        LinkButton lnkDynamic = new LinkButton();
        lnkDynamic.Click += new EventHandler(LinkClick);
        lnkDynamic.ID = "lnkDynamic123";
        lnkDynamic.Text = "lnkDynamic123";
        holder.Controls.Add(lnkDynamic);

        string IDValue = GetPostBackControlId(this.Page);

        if (IDValue == lnkDynamic.ID)
            LinkClick(lnkDynamic, new EventArgs());
    }
}

ここでクリックイベントハンドラーを呼び出すと、標準のASP.NETページライフサイクルをより厳密に模倣します。この場合、ポストバックイベントの処理はロードイベントの後に発生します。

編集:

LinkBut​​tonを作成する前にコントロールIDを決定する必要がある場合は、リンクボタンIDの命名スキームを作成できます。たとえば、lnkDynamic_1、lnkDynamic_2など Request["__EVENTTARGET"]には、「ctl00 $ mc$lnkDynamic_1」などの自動生成されたコントロールIDが含まれます。これを使用して、どのLinkBut​​tonがポストバックを引き起こしたかを特定できます。

于 2013-01-29T10:43:39.063 に答える
2

ポスト バック コントロール ID を正しく取得しているのにFindControl何も返さない場合は、マスター ページを使用している可能性があります。基本的に、名前付けコンテナーsomeControl.FindControl(id)にあるコントロールを検索します。someControl.NamingContainerしかし、あなたの場合、Button1コントロールはContentPlaceHolder1名前付けコンテナーである にあり、名前付けコンテナーに直接含まれてPageいないため、 を呼び出しても見つかりませんPage.FindControl。探しているコントロールがどのネーミング コンテナに配置されるか予測できない場合 (たとえば、2 つの異なるコンテンツ プレースホルダーからの 2 つの異なるボタンによってポスト バックが発生する可能性がある場合)、検索する拡張機能を作成できます。次のように、再帰的にコントロールを作成します。

public static class Extensions
{
    public static Control FindControlRecursively(this Control control, string id)
    {
        if (control.ID == id)
            return control;
        Control result = default(Control);
        foreach (Control child in control.Controls)
        {
            result = child.FindControlRecursively(id);
            if (result != default(Control)) break;
        }
        return result;
    }
}

ただし、このメソッドは、指定された ID で見つかった最初のコントロールを返すため、注意して使用してください (同じ ID を持つ複数のコントロールを使用できますが、それら異なる名前付けコンテナーにある必要があります。名前付けコンテナーは、コントロールを区別するためのものです)。名前空間が同じ名前を持つクラスを区別することを意図しているように、同じ ID を持つ)。

または、オーバーロードを使用することもできますがFindControl(string id, int pathOffset)、かなりトリッキーだと思います。

また、この質問をチェックしてください。

于 2013-02-01T08:42:17.267 に答える
2

最初のアプローチ (お勧めしませんが、より柔軟です)

まったく別のアプローチの 1 つは、フォームに非表示フィールドを追加することです。

この隠しフィールドの値は、デフォルトではfalse のようなものかもしれません。

動的コントロールが再度追加される原因となる動的ボタンの 1 つをクリックする場合は、ポストバックを実行する前に、クライアント側で非表示フィールドの値をtrueに変更するだけです (最終的には、クライアント側の onclick ハンドラーを変更する必要があります)。これを実現するために)。

もちろん、コントロールIDや引数など、より多くの情報をそのようなフィールドに保存することは可能です(ただし、他の回答で説明されているように、これらの値を取得できます)。この場合、命名スキーマは必要ありません。

この隠しフィールドは「静的」である可能性があります。したがって、いつでもコードビハインドでアクセスできます。とにかく、誰もその値をいじったり、これらの動的リンクの 1 つから発信されたように見えるコールバックを偽造したりしないようにするために、何かを実装することをお勧めします。

ただし、このアプローチ全体は、コントロールの ID を取得するのに役立ちます。コントロールを再度作成するまで、NamingContainer.FindControl を介してインスタンスを取得することはできません (既に他の回答で述べたように;))。作成した場合は、もう探す必要はありません。

2 番目のアプローチ (制約があるため適切ではない可能性があります)

クリーンな方法で実行したい場合は、何かがクリックされたかどうかに関係なく、コントロール OnLoad を作成する必要があります。さらに、ダイナミック コントロール ID は、最初にクライアントに送信したものと同じである必要があります。Click または Command イベントをサブスクライブし、可視性を false に設定します。クリック イベント ハンドラー内で、送信者の可視性を再度 true に設定します。これは、そのリンクが作成されたかどうかは気にせず、代わりにクライアントに送信したくないことを意味します。もちろん、以下の例は単一のリンクに対してのみ機能します (ただし、リンクのグループ全体をカバーするように簡単に変更できます)。

public void Page_Load(object sender, EventArgs e)
{
  LinkButton dynamicButton = new LinkButton();
  dynamicButton.ID = "linkDynamic123";
  // this id needs to be the same as it was when you 
  // first sent the page containing the dynamic link to the client
  dynamicButton.Click += DynamicButton_Click;
  dynamicButton.Visible = false;
  Controls.Add(dynamicButton);
}

public void DynamicButton_Click(object sender, EventArgs e)
{
  // as you created the control during Page.Load, this event will be fired. 
  ((LinkButton)sender).Visible = true;
}
于 2013-02-01T13:01:16.623 に答える