3

画像付きのボタンとして機能するカスタム Web コントロールを作成しました。DefaultButtonこれをASP.NET パネル コントロールのパラメータのターゲットとして設定できるようにしたいと考えています。IButton インターフェイスを実装しましたが、コントロールを使用してページをロードしてもエラーは発生しません。ただし、そのパネル内のテキスト ボックスで Enter キーを押すと、コントロールの Click イベントは発生しません。コントロールを標準の ASP.NET ボタンに置​​き換えると、すべて正常に動作します。

テキスト ボックス、カスタム ボタンのインスタンス、および標準の asp.net ボタンを含むパネルを含むテスト ページがあります。ボタンは、テキスト ボックスを呼び出し元の ID に変更するイベント ハンドラーに接続されています。

パネルの DefaultButton が ASP.NET ボタンに設定されている場合、次のボックスで Enter キーを押すと正しく機能します。ページがポストバックされ、テキスト ボックスに標準ボタンの名前が入力されます。パネルの DefaultButton が my ボタンに設定されている場合、テキスト ボックスで Enter キーを押すと、ページがポストバックされますが、Click イベントは発生しません。ボタンを手動でクリックすると、正しく機能します。

Panel コントロールからのイベントを処理するために、カスタム コントロールに何を追加する必要があるかを知っている人はいますか? Button のソース コードで 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>
4

2 に答える 2

1

クライアント側のマークアップを表示します (ブラウザーでソースを表示)。この機能は、ソース内で次のようにレンダリングする必要があります。

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

これが正しく設定されている場合、ページで... 2番目のパラメーターがボタンのパラメーターと正しく一致しない場合、ボタンは正しく起動しません。これにはいくつかの理由が考えられます。

  1. レンダリング フェーズ中にクライアント/一意の ID をレンダリングするか、AddAttributesToRender を呼び出しますか。ClientID プロパティは、クライアント側の要素を機能にリンクする方法として必要であり、id 属性にレンダリングする必要があります。これは、AddAttributesToRender メソッドで発生します。
  2. その JS メソッドで null が表示される場合、多くの場合、そのプロパティがオーバーライドされているために、クライアント ID を取得できません。

HTH。

于 2010-01-25T16:40:39.343 に答える
1

WebForm_FireDefaultButton 関数が機能する方法は、問題の要素で click() イベントを明示的に探すことです。OnClick 属性ではなく、element.click() を呼び出す機能について言及していることに注意してください。ブラウザーは、特定の要素に対してこれを自動的にリンクしますが、コントロールがレンダリングする方法であるリンクはリンクしません。LinkBut​​ton を使用すると、同じ動作に気付くでしょう。これにはいくつかの方法があります。この投稿のように、WebForm_FireDefaultButton JavaScript 関数をオーバーライドできます。

ページ上のボタンをリンクし、それをデフォルト ボタンとして設定します。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);
}
于 2010-01-25T17:31:16.777 に答える