Подтвердить что ты не робот

Как проверить, была ли обратная связь вызвана кнопкой динамической ссылки

У меня есть кнопка управления. При нажатии этой кнопки мне нужно добавить кнопку ссылки динамически. Кнопка Link требует обработчика событий. Следовательно, динамическая кнопка Link сначала добавляется в Page_Load и очищается и добавляется снова в обработчик щелчка кнопки. Пожалуйста, прочитайте Обработчики событий динамических элементов управления для понимания бизнес-требований для этого.

Я прочитал В ответ на вопрос, как я могу проверить, какой элемент управления вызывает обратную передачу в событии Page_Init для идентификации элемента управления, вызвавшего обратную передачу (внутри Page_Load). Но он не работает для моего сценария.

Что нужно сделать, чтобы подтвердить, была ли обратная связь вызвана кнопкой ссылки (внутри Page_Load)?

Примечание. Обратитесь к следующему сценарию, где это неизбежно. https://codereview.stackexchange.com/info/20510/custom-paging-in-asp-net-web-application

Примечание 1: Мне нужно получить идентификатор управления обратной связью в качестве первого шага внутри if (Page.IsPostBack). Мне нужно добавить кнопки управления динамическими ссылками, только если это обратная передача от кнопки или кнопки ссылки. Там будут другие элементы управления, которые вызывают обратную передачу. Для таких postbacks мы не должны выполнять этот код.

Примечание 2: я получаю пустую строку для Request["__EVENTARGUMENT"] в Page_Load

Связанный вопрос. По какому event динамические элементы управления будут доступны на странице (для использования в FindControl). @Tung говорит: "Ваш метод GetPostBackControlId правильно получает имя элемента управления, вызвавшего обратную передачу, но он не может найти элемент управления с этим идентификатором через страницу. FindControl, потому что ссылка еще не создана, и поэтому страница не знать о его существовании".

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;
}
}

ССЫЛКА

4b9b3361

Ответ 1

Откат в asp.net выполняется функцией java script __doPostback (источник, параметр)

поэтому в вашем случае это будет

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

Итак, в коде ниже сделайте следующее

    var btnTrigger = Request["__EVENTTARGET"]; 

     if(btnTrigger=="lnkDynamic123") 
{
}

--- это скажет, что это ваша ссылка, которая вызывает обратную передачу

Ответ 2

Вы можете переместить вызов методу GetPostBackControlId после добавления LinkButton на страницу:

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());
    }
}

Вызов обработчика событий click здесь также более точно имитирует стандартный жизненный цикл ASP.NET, где обработка событий Postback происходит после события загрузки.

Edit:

Если идентификатор элемента управления должен быть определен до создания LinkButtons, вы можете создать схему именования для идентификаторов кнопки ссылки, например. lnkDynamic_1, lnkDynamic_2 и т.д. Request["__EVENTTARGET"] затем будет содержать автоматически сгенерированный идентификатор управления, такой как "ctl00 $mc $lnkDynamic_1", который вы можете использовать для определения того, какой LinkButton вызвал обратную передачу.

Ответ 3

Если вы правильно получаете контрольный идентификатор сообщения, но FindControl ничего не возвращает, то это, вероятно, потому, что вы используете главную страницу. В основном, someControl.FindControl(id) выполняет поиск элементов управления, которые находятся в контейнере имен someControl.NamingContainer. Но в вашем случае элемент Button1 находится в ContentPlaceHolder1, который является контейнером именования, а не непосредственно в контейнере имен Page, поэтому вы не найдете его, вызвав Page.FindControl. Если вы не можете предсказать, в каком контейнере для именования выбран элемент управления, который вы ищете (например, post back может быть вызван двумя разными кнопками из двух разных заполнителей содержимого), тогда вы можете написать расширение, которое будет искать управление рекурсивно, например:

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 (и вы можете иметь несколько элементов управления с одним и тем же идентификатором, но они должны быть в разных именах контейнеры, именованные контейнеры предназначены для различения элементов управления с одинаковыми идентификаторами, так же как пространства имен предназначены для разграничения между классами с одинаковыми именами).

В качестве альтернативы вы можете попытаться использовать перегрузку FindControl(string id, int pathOffset), но я думаю, что это довольно сложно.

Кроме того, проверьте этот вопрос вне.

Ответ 4

Первый подход (не рекомендуется, но он более гибкий)

Один совершенно другой подход - хотя я действительно не чувствую, что должен его продвигать, - это добавить скрытое поле в форму.

Значение этого скрытого поля по умолчанию может быть ложным.

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

Конечно, можно было бы хранить больше информации в таком поле, как идентификатор элементов управления и аргумент (но вы можете получить эти значения, как описано в других ответах). В этом случае не требуется схема именования.

Это скрытое поле может быть "статическим". Таким образом, он будет доступен в коде за все время. Во всяком случае, вы можете реализовать что-то, чтобы убедиться, что никто не играет со своими значениями и подделывает обратный вызов, который выглядит так, как будто он создан из одной из этих динамических ссылок.

Однако весь этот подход просто помогает вам получить идентификатор элемента управления. Пока вы не создадите элемент управления еще раз, вы не сможете получить экземпляр через NamingContainer.FindControl(как уже упоминалось в других ответах уже;)). И если вы его создадите, вам больше не нужно его искать.

Второй подход (возможно, не подходит из-за его противопоказаний)

Если вы хотите сделать это чистым способом, вам нужно создать свои элементы управления OnLoad, независимо от того, было ли что-то нажато или нет. Кроме того, идентификатор динамического контроля должен быть таким же, как и тот, который вы отправили клиенту в первую очередь. Вы подписываетесь на событие 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;
}