1

WebパーツコントロールにGridViewとDetailsViewを持つコードを継承しました。

DetailsViewは、TypeAとTypeBなどの2種類のオブジェクトを作成できます。

GridViewをオブジェクトタイプでフィルタリングするドロップダウンリストがあり、DetailsViewには自動的に生成された[挿入]ボタンがあります。

<asp:DetailsView ID="myDetailsView"  
    AutoGenerateInsertButton="True"
    AutoGenerateEditButton="True" 
    AutoGenerateRows="false" 
    OnItemUpdating="OnItemUpdating"
    DefaultMode="ReadOnly" 
    OnDataBound="OnDetailsViewBound"
    OnItemInserting="OnItemInserting" 
    OnModeChanging="OnDetailsViewModeChanging"        
    runat="server">

私は尋ねられました:

  1. GridViewのフィルターを削除します。と
  2. 新規ボタン/リンクを2つに分割して、各タイプのオブジェクトを作成するための個別のボタンがあるようにします。

フィルタを削除するということは、作成しているオブジェクトの種類を追跡するための別の方法が必要であることを意味します。上記を次のように変更して、新しいリンクを分割しました。

<asp:DetailsView ID="myDetailsView"  
    AutoGenerateInsertButton="False"
    AutoGenerateEditButton="True" 
    AutoGenerateRows="false" 
    OnItemUpdating="OnItemUpdating"
    DefaultMode="ReadOnly" 
    OnDataBound="OnDetailsViewBound"
    OnItemInserting="OnItemInserting" 
    OnModeChanging="OnDetailsViewModeChanging"        
    runat="server">

と追加

 <FooterTemplate>
        <asp:TemplateField>
            <ItemTemplate>
                <asp:LinkButton runat="server" ID="lnkCreateNewTypeA" CommandName="New" CommandArgument="TypeA" CssClass="buttonlink">New Type A</asp:LinkButton>
                <asp:LinkButton runat="server" ID="lnkCreateNewTypeB" CommandName="New" CommandArgument="TypeB" CssClass="buttonlink">New Type B</asp:LinkButton>
            </ItemTemplate>
        </asp:TemplateField>
 </FooterTemplate>

まだフィルターを削除していないので、Newコマンドを使用しているので、変更は現在以前と同じように機能します。私ができることを望んでいたのは、なんらかの方法でNewイベントをキャプチャして、CommandArgument値を非表示フィールドに配置できるようにすることです。これにより、DetailsViewは、作成するオブジェクトのタイプを判別し、フィールドを表示/非表示にします。コード内のすべてのイベントハンドラーにブレークポイントを設定すると、最初にブレークするのはOnDetailsViewModeChangingであり、これはCommandArgumentにアクセスできません。

OnItemCommand(接続されている場合)は、DetailsView内のいずれかのボタンが押されたときにトリガーされ、CommandArgumentにアクセスできますが、このメソッド内で、次の場合に発生する一連のイベントを模倣するために正確に何を行う必要があるかわかりません。自動生成されたボタンを使用します。

CommandArgumentを取得してOnItemCommandイベントハンドラーでキャプチャするための唯一のオプションですか、それともNewコマンドでトリガーされる他のイベントがありますか?

Newコマンドがトリガーされたときに発生する一連のイベントについて誰かに説明してもらえますか?

モードが挿入に変わることをどこかで読みましたが、他に何をするのかわかりません。「挿入」リンクがクリックされるまで、OnItemInsertingメソッドは呼び出されないと思います。

どんな助けでもありがたいです!!


編集:

DetailsViewイベントでこのリンクを見つけましたが、質問に答えていません。 http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.detailsview_events.aspx


編集:

私は以下を追加しようとしました:

ascxで:

<asp:DetailsView ID="myDetailsView"
    ...
    OnItemCommand="OnItemCommand"
    ...
    runat="server">

    ...

    <asp:TemplateField HeaderText="Object Type" HeaderStyle-CssClass="columnHeader">
        <ItemTemplate>
            <asp:HiddenField runat="server" ID="hidObjectType" Value=""/>
            <asp:Label runat="server" ID="lblObjectType"></asp:Label>
        </ItemTemplate>
    </asp:TemplateField>

コードビハインド:

protected void OnItemCommand(object sender, DetailsViewCommandEventArgs e)
{
    if (e.CommandName.Equals("New"))
    {
        var objectType = e.CommandArgument.ToString();

        HiddenField typeHidden = this.myDetailsView.FindControl("hidObjectType") as HiddenField;
        if (typeHidden != null)
        {
            typeHidden.Value = objectType;
        }

        Label typeLabel = this.myDetailsView.FindControl("lblObjectType") as Label;
        if (typeLabel != null)
        {
            typeLabel.Text = objectType;
        }
    }
}

this.myDetailsView.ChangeMode(DetailsViewMode.Insert);OnDetailsViewModeChangingイベントハンドラーが引き続きトリガーされるため、このメソッドでモード()を設定する必要がないことがわかりました。これにより、コントロールが検出され、それらの値が正しく設定されます。OnDetailsViewModeChangingで値を再度確認すると、それらの値はまだ設定されていますが、このメソッドのロジックの一部として、

this.myDetailsView.DataBind()

これによりポストバックが発生し、この時点で値が失われます。追加してみました

EnableViewState="True"

しかし、これは何の違いもありませんでした。this.EnsureChildControls()ページのライフサイクル(http://spazzarama.files.wordpress.com/2009/02/aspnet_page-control-life-cycle.pdf)を確認しましたが、おそらく役立つと思いましたが、違いはありませんでした。

別の方法は、セッションに値を保存することですが、私はむしろ保存しません。

4

1 に答える 1

0

私の知る限り、OnItemCommandすべてのコマンドをキャプチャする「New」コマンドを除いて、「New」コマンドをキャプチャするイベントはありません。(注:LinkBut​​tonに設定されていることを確認する必要があります。CausesValidation="False"そうしないと、コードがに侵入しませんOnItemCommand)。

コードをステップ実行すると、次のことが発生しました。

  1. リンクボタンが押された後、OnItemCommandがトリガーされます。CommandName = "New"で、ここでCommandArgumentを取得できます
  2. 次のOnModeChangingがトリガーされます。e.NewMode="挿入"。私が見たすべての例から、ここでは、DetailsViewでChangeModeを呼び出してから、Databind()を呼び出します。
  3. 次のOnDataBoundは、Databind()を呼び出した結果としてトリガーされます。

さまざまなイベント間で非表示の変数の値を保持する方法が見つからなかったため、セッション変数を使用することになりました。誰かがそれを望む場合に備えて、コードは以下にあります。

ASCXでのDetailsView宣言:

    <asp:DetailsView ID="myDetailsView"  
        AutoGenerateInsertButton="False"
        AutoGenerateEditButton="True" 
        AutoGenerateRows="false" 
        OnItemInserting="OnItemInserting" 
        OnItemUpdating="OnItemUpdating"
        OnItemCommand="OnItemCommand"
        DefaultMode="ReadOnly" 
        OnDataBound="OnDetailsViewBound"
        OnModeChanging="OnDetailsViewModeChanging"        
        runat="server">

コードビハインド:

定数宣言..。

    private const string SESSIONKEY_MYVALUE = "MyValue";
    private const string DEFAULT_OBJECTTYPE = "TypeA";

OnItemCommandイベントハンドラ...

    protected void OnItemCommand(object sender, DetailsViewCommandEventArgs e)
    {
        if (e.CommandName.Equals("New", StringComparison.InvariantCultureIgnoreCase))
        {
            var objectType = e.CommandArgument.ToString();

            HiddenField typeHidden = this.myDetailsView.FindControl("hidObjectType") as HiddenField;
            if (typeHidden != null)
            {
                typeHidden.Value = objectType;
            }

            HttpContext.Current.Session[SESSIONKEY_MYVALUE] = objectType;
        }
    }

OnModeChangingイベントハンドラー...

    protected void OnDetailsViewModeChanging(Object sender, DetailsViewModeEventArgs e)
    {
        if (e.NewMode == DetailsViewMode.Insert)
        {
            this.myDetailsView.ChangeMode(DetailsViewMode.Insert);
            this.myDetailsView.DataBind();
        }
    }

OnDataBoundイベントハンドラ...

    protected void OnDetailsViewBound(object sender, EventArgs e)
    {
        if (this.myDetailsView.CurrentMode == DetailsViewMode.Insert)
        {
            var sessionVar = HttpContext.Current.Session[SESSIONKEY_MYVALUE];
            var objectType = sessionVar == null ? 
                DEFAULT_OBJECTTYPE : 
                sessionVar.ToString();

            var typeHidden = this.myDetailsView.FindControl("hidObjectType") as HiddenField;

            if (typeHidden != null)
            {
                typeHidden.Value = objectType;
            }
        }
    }
于 2012-12-05T05:09:30.680 に答える