Использование пользовательского WebControl в качестве DefaultButton для Panel - PullRequest
3 голосов
/ 25 января 2010

Я создал собственный веб-элемент управления, который будет действовать как кнопка с изображением. Я хотел бы иметь возможность установить это в качестве цели параметра DefaultButton элемента управления ASP.NET Panel. Я реализовал интерфейс IButton, и при загрузке страницы с помощью элемента управления не выдается никакой ошибки. Однако, когда я нажимаю ввод в текстовом поле на этой панели, событие Click элемента управления не возникает. Когда я заменяю свой элемент управления стандартной кнопкой ASP.NET, все работает нормально.

У меня есть тестовая страница с панелью, содержащей текстовое поле, экземпляр моей пользовательской кнопки и стандартная кнопка asp.net. Кнопки подключены к обработчику событий, который изменит текстовое поле на идентификатор вызывающего абонента.

Когда для кнопки DefaultButton панели установлено значение кнопки ASP.NET, нажатие клавиши ввода в следующем окне работает правильно - страница отправляется назад, а текстовое поле заполняется именем стандартной кнопки. Когда для кнопки DefaultButton на панели установлено значение «Моя кнопка», нажатие клавиши ввода в текстовом поле вызывает обратную передачу страницы, но событие Click не вызывается. Нажатие кнопки вручную работает правильно.

Кто-нибудь знает, что я должен добавить к своему пользовательскому элементу управления, чтобы он обрабатывал событие, исходящее от элемента управления Panel? Я использую Reflector в исходном коде кнопки, но не могу определить, что делает это возможным.

Я разместил источник элемента управления ниже и соответствующий источник тестовой страницы.

Источник управления:

public class NewButton : WebControl, IPostBackEventHandler, IButtonControl
{
    public NewButton() : base(HtmlTextWriterTag.A) { }

    public event EventHandler Click;

    public event CommandEventHandler Command;

    public string Text
    {
        get { return ViewState["Text"] as string; }
        set { ViewState["Text"] = value; }
    }

    public string ImageUrl
    {
        get { return ViewState["ImageUrl"] as string; }
        set { ViewState["ImageUrl"] = value; }
    }

    protected virtual void OnClick(EventArgs e)
    {
        if (Click != null)
            Click(this, e);
    }

    protected virtual void OnCommand(CommandEventArgs e)
    {
        if (Command != null)
            Command(this, e);
    }

    protected override void AddAttributesToRender(HtmlTextWriter writer)
    {
        base.AddAttributesToRender(writer);

        writer.AddAttribute(HtmlTextWriterAttribute.Class, "Button");
        writer.AddAttribute(HtmlTextWriterAttribute.Onclick, Page.ClientScript.GetPostBackEventReference(this, "Click"));
    }

    protected override void RenderContents(HtmlTextWriter writer)
    {
        // base.RenderContents(writer);

        writer.WriteFullBeginTag("span");
        writer.WriteFullBeginTag("span");

        if (!String.IsNullOrEmpty(ImageUrl))
        {
            writer.WriteBeginTag("img");
            writer.WriteAttribute("src", Page.ResolveClientUrl(ImageUrl));
            writer.Write(HtmlTextWriter.SelfClosingTagEnd);
            writer.Write(" ");
        }

        writer.WriteEncodedText(Text);
        writer.WriteEndTag("span");
        writer.WriteEndTag("span");
    }

    public void RaisePostBackEvent(string eventArgument)
    {
        if (this.CausesValidation)
        {
            Page.Validate(this.ValidationGroup);
        }
        OnClick(EventArgs.Empty);
        OnCommand(new CommandEventArgs(this.CommandName, this.CommandArgument));
    }

    public bool CausesValidation
    {
        get { return ViewState["CausesValidation"] as bool? ?? true; }
        set { ViewState["CausesValidation"] = value; }
    }

    public string CommandArgument
    {
        get { return ViewState["CommandArgument"] as string; }
        set { ViewState["CommandArgument"] = value; }
    }

    public string CommandName
    {
        get { return ViewState["CommandName"] as string; }
        set { ViewState["CommandName"] = value; }
    }

    public string PostBackUrl
    {
        get { return ViewState["PostBackUrl"] as string; }
        set { ViewState["PostBackUrl"] = value; }
    }

    public string ValidationGroup
    {
        get { return ViewState["ValidationGroup"] as string; }
        set { ViewState["ValidationGroup"] = value; }
    }
}

Код для вызова:

<asp:Panel ID="Panel1" runat="server" CssClass="StandardForm" DefaultButton="NewButton1">
    <asp:TextBox runat="server" ID="text1" Columns="40" />
    <MyControls:NewButton ID="NewButton1" runat="server" Text="Test" OnClick="OnClick" />
    <asp:Button runat="server" ID="OldButton1" OnClick="OnClick" Text="Test" />
</asp:Panel>

Код сзади:

   protected void OnClick(object sender, EventArgs args)
    {
        text1.Text = "Click event received from " + ((WebControl) sender).ID;
    }

Элемент управления выглядит следующим образом:

<div id="ctl00_MainContent_Panel1" class="StandardForm" onkeypress="javascript:return WebForm_FireDefaultButton(event, 'ctl00_MainContent_NewButton1')">
    <input name="ctl00$MainContent$text1" type="text" size="40" id="ctl00_MainContent_text1" />
    <a id="ctl00_MainContent_NewButton1" class="Button" onclick="__doPostBack('ctl00$MainContent$NewButton1','')"><span><span>Test</span></span></a>
    <input type="button" name="ctl00$MainContent$OldButton1" value="Test" onclick="javascript:__doPostBack('ctl00$MainContent$OldButton1','')" id="ctl00_MainContent_OldButton1" />
</div>

Ответы [ 2 ]

1 голос
/ 25 января 2010

Принцип работы функции WebForm_FireDefaultButton заключается в том, что она явно ищет событие click () для рассматриваемого элемента. Обратите внимание, что я имею в виду возможность вызова element.click (), а не атрибута OnClick. Браузер свяжет это автоматически для определенных элементов, но не для ссылок, как ваш контроль рендеринга. Вы заметите то же поведение, если будете использовать LinkButton. Есть несколько способов обойти это. Вы можете переопределить функцию javascript WebForm_FireDefaultButton, как показано в этом сообщении:

Кнопка ссылки на странице и установка ее в качестве кнопки по умолчанию, отлично работают в IE, но не в Mozila

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

protected override void OnPreRender(EventArgs e)
{
    string clickString = string.Format("document.getElementById('{0}').click = function() {{ {1} }};", this.ClientID, Page.ClientScript.GetPostBackEventReference(this, "Click"));

    Page.ClientScript.RegisterStartupScript(this.GetType(), "click_hookup_" + this.ClientID, clickString, true);
}
1 голос
/ 25 января 2010

Просмотр разметки на стороне клиента (просмотр источника в браузере); эта функция должна отображать что-то вроде в источнике:

javascript:return WebForm_FireDefaultButton(event, 'ct100$bodyplaceholder$newbutton1')";

на вашей странице, если он настроен правильно ... Если второй параметр не соответствует вашим кнопкам, он не будет работать правильно. Это может быть по нескольким причинам:

  1. Отрисовываете ли вы клиент / уникальный идентификатор на этапе рендеринга или вызываете AddAttributesToRender. Требуется свойство ClientID, так как он будет связывать клиентский элемент с функцией, и он должен отображаться в атрибуте id. Это происходит в методе AddAttributesToRender.
  2. Если в этом методе JS вы видите null, он не может получить идентификатор клиента, часто потому, что это свойство переопределено.

НТН.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...