none
asp.net2010のGridViewのRowCommandの挙動が2008と異なる RRS feed

  • 質問

  • はじめまして、hatukieです。

    正常に動作していた、asp.net 2008のプログラムが、
    asp.net 2010にバージョンアップ後、不具合が生じました。
    コンパイルのみのバージョンアップで、プログラムに改変はありません。

    grdParentの中に、grdChildがあり、
    GridViewコントロールをネストさせています。

    asp.net 2008では、
    grdChildのRowCommandイベントが発生した場合、
    grdChildのRowCommandだけ発生していたのですが、

    asp.net 2010にバージョンアップ後は、
    grdChildのRowCommandイベントが発生した後に、
    grdParentのRowCommandも発生します。

    その際、grdParentのRowCommandの
    CommandNameとCommandArgumentは、
    grdChildのパラメータが渡ってしまいます。

    不具合の回避策としては、
    CommandNameがgrdParentとgrdChildと同じになっているため、
    違う値にすれば正常動作すると思うのですが、
    お聞きしたいのは、.Netの仕様変更であるか、
    または別の原因があるのかご存知でしたらお教え頂ければと思います。

    (※.Netframework4.0 がバージョンアップされた場合、
    再度不具合が出ると困るため、把握しておきたい事が理由になります。)

    どうぞ宜しくお願い致します。

    ▼開発/動作環境
    .net 2008 Professional + (xp or ms-server 2008)
    .net 2010 Professional + (xp or ms-server 2008)
    Windows Update適用済み

     

     

    2011年2月27日 5:33

回答

  • > ただ、GridViewとは直接関係するとは考えられないのですが・・・

    この根拠は?

    http://msdn.microsoft.com/ja-jp/library/s57a598e.aspx?appId=Dev10IDEF1&l=JA-JP&k=k(VS.AMBIENT);k(TargetFrameworkMoniker-"SILVERLIGHT&k=VERSION=V3.0")&rd=true#aspnet_web_forms

    上記ページをみると、ASP.NET 4でWeb Formのコントロールは基本的なレベル(Controlクラスのレベル)から手が入っていることがわかります。
    GridViewだと「データコントロールの行選択の持続」の項目ではっきりコントロールの動作がいままでのバージョンと変わっているところがある、というのが述べられています。

    .NET Framework 2から3、3.5まではベースとなるランタイムが同じで、dllの追加、といったバージョンアップだったので、コントロールの挙動も大きく変わることはありませんでしたが、4ではランタイムも別で各種コントロールも別のものとして用意されていますから、まず違うことを前提に考えたほうがいいと思います。

    #あ、アセンブリのバージョンの話しようと思ったら、C:\Windows\assembly には3.5までのアセンブリしかないんだった。
     4になってどこにいったか、って誰のBlogに書いてあったんだっけかな。。。
     まあ、アセンブリの場所が違うほどバージョンアップで異なってます、ってことで(w


    あおい情報システム株式会社 小野修司(どっとねっとふぁん)
    • 回答としてマーク 山本春海 2011年3月18日 8:27
    2011年2月28日 8:38
  • 今さらながらのレスですが・・・

    > grdChildのRowCommandが発生した後、
    > grdParentのRowCommandが発生しますが、

    当方でも検証してみましたが、こちらは再現できました。

    ASP.NET 3.5 と ASP.NET 4 の GridView コントロールの仕様(?)の違いのよう
    です。

    ただし、子の GridView のボタンの CommandName を Select とか Cancel など組
    み込み機能を呼び出すための名前にしておくと、子の GridView のボタンクリック
    で親の GridView の RowCommand イベントは発生しないようです。

    > grdParent_RowCommand内では、
    > CommandArgumentの値は、btnTestParentButtonに設定してある値で、
    > CommandNameの値は、btnTestChildButtonの値として渡っておりました。

    こちらは再現できませんでした。

    子の GridView のボタンクリックで、親の GridView の RowCommand イベントが発
    生しますが、ハンドラに引数として渡される GridViewCommandEventArgs オブジェ
    クトの CommandName, CommandArgument プロパティ値は、子の GridView のボタン
    に設定したものになるはずです。

    検証に使ったコードを以下にアップしておきますので、確認してみてください。デ
    ータベースは Microsoft が提供しているサンプルデータベースの Northwind を使
    用しました。


    <%@ Page Language="C#" %>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <script runat="server">

        int n = 0;
        protected void SqlDataSource2_Selecting(object sender, SqlDataSourceSelectingEventArgs e)
        {
            e.Command.Parameters["@CustomerID"].Value =
                (string)GridView1.DataKeys[n].Value;
            n++;
        }

        protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
        {
            Label1.Text =
                ((GridView)sender).ID +", " + e.CommandName + ", " +
                e.CommandArgument.ToString() + "<br />";
        }


        protected void GridView2_RowCommand(object sender, GridViewCommandEventArgs e)
        {
            Label2.Text =
                ((GridView)sender).ID + ", " + e.CommandName +  ", " +
                e.CommandArgument.ToString();
        }
    </script>

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head id="Head1" runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
            <asp:Label ID="Label1" runat="server"></asp:Label>
            <asp:Label ID="Label2" runat="server"></asp:Label>

            <asp:SqlDataSource ID="SqlDataSource1"
                runat="server"
                ConnectionString="<%$ ConnectionStrings:Northwind %>"
                SelectCommand="SELECT TOP 10 [CustomerID] FROM [Customers]">
            </asp:SqlDataSource>

            <asp:SqlDataSource ID="SqlDataSource2"
                runat="server"
                ConnectionString="<%$ ConnectionStrings:Northwind %>"
                SelectCommand="SELECT TOP 5 [OrderID], [OrderDate], [Freight]
                               FROM [Orders]
                               WHERE ([CustomerID] = @CustomerID)"
                OnSelecting="SqlDataSource2_Selecting">
                <SelectParameters>
                    <asp:Parameter Name="CustomerID" Type="String" />
                </SelectParameters>
            </asp:SqlDataSource>

            <asp:GridView ID="GridView1"
                runat="server"
                AutoGenerateColumns="False"
                DataKeyNames="CustomerID"
                DataSourceID="SqlDataSource1"
                OnRowCommand="GridView1_RowCommand">
                <Columns>
                    <asp:TemplateField HeaderText="選択" ShowHeader="False">
                        <ItemTemplate>
                            <asp:Button ID="Button1"
                                runat="server"
                                CommandName="Parent"
                                CommandArgument='<%# Eval("CustomerID") %>'
                                Text="選択" />
                        </ItemTemplate>
                    </asp:TemplateField>
                    <asp:BoundField
                        DataField="CustomerID"
                        HeaderText="CustomerID" />
                    <asp:TemplateField HeaderText="Order Details">
                        <ItemTemplate>
                            <asp:GridView ID="GridView2"
                                runat="server"
                                AutoGenerateColumns="False"
                                DataKeyNames="OrderID"
                                DataSourceID="SqlDataSource2"
                                OnRowCommand="GridView2_RowCommand">
                                <Columns>
                                    <asp:BoundField
                                        DataField="OrderID"
                                        HeaderText="OrderID"
                                        InsertVisible="False"
                                        ReadOnly="True"
                                        SortExpression="OrderID" />
                                    <asp:BoundField
                                        DataField="OrderDate"
                                        HeaderText="OrderDate"
                                        SortExpression="OrderDate"
                                        DataFormatString="{0:yyyy/MM/dd}" />
                                    <asp:BoundField
                                        DataField="Freight"
                                        HeaderText="Freight"
                                        SortExpression="Freight"
                                        DataFormatString="${0:N2}"/>
                                    <asp:TemplateField HeaderText="選択" ShowHeader="False">
                                        <ItemTemplate>
                                            <asp:Button ID="Button2"
                                                runat="server"
                                                CommandName="Child"
                                                CommandArgument='<%# Eval("OrderID") %>'
                                                Text="選択" />
                                        </ItemTemplate>
                                    </asp:TemplateField>
                                </Columns>
                            </asp:GridView>
                        </ItemTemplate>
                    </asp:TemplateField>
                </Columns>
            </asp:GridView>
         </form>
    </body>
    </html>


    以下、今回の問題とは関係ないことですが・・・

    > asp.net 2008, asp.net 2010は、
    > Microsoft Visual Studio 2008/2010の中のasp.netを省略して書きました。

    その言い方は正しくなくて、正しい言い方は ASP.NET 3.5 とか ASP.NET 4
    だと思いますが、いかがですか?

    開発サーバーを利用しているのでなければ、開発環境のバージョンの違いは
    今回の話とは何も関係ないです。関係があるのは .NET Framework のバージ
    ョンの違いです。

    Visual Studio 2010 を使っても、最初に「新しいプロジェクト」または「新
    しい Web サイト」を作るときに、.NET Framework のバージョンを Visual
    Studio 2008 と同じにすれば、結果は同じになるはずです。

    • 回答としてマーク 山本春海 2011年3月18日 8:27
    2011年3月6日 5:31

すべての返信

  • 訂正させて頂きます。

    > その際、grdParentのRowCommandの
    > CommandNameとCommandArgumentは、
    > grdChildのパラメータが渡ってしまいます。


    間違いでした。

    grdParentの行の中には、1つづつgrdChildが存在します。
    grdParentの行内には、btnTestParentButtonがあり、
    grdChildには、btnTestChildButtonがあります。

    grdChildのRowCommandが発生した後、
    grdParentのRowCommandが発生しますが、

    grdParent_RowCommand内では、
    CommandArgumentの値は、btnTestParentButtonに設定してある値で、
    CommandNameの値は、btnTestChildButtonの値として渡っておりました。

    もちろん、btnTestParentButtonを押したわけではなく、
    btnTestChildButtonを押してこの現象となります。

    以上訂正とさせて頂きます。

    2011年2月27日 6:49
  • > 正常に動作していた、asp.net 2008のプログラムが、
    > asp.net 2010にバージョンアップ後、不具合が生じました。
    > コンパイルのみのバージョンアップで、プログラムに改変はありません。

    asp.net 2008 とか asp.net 2010 って何ですか? .NET Framework 3.5
    と .NET Framework 4 のことですか?

    .NET 3.5 と .NET 4 では web.config に大きな違いがありますし、IIS
    の設定も変わってきますが、「コンパイルのみのバージョンアップ」で
    そのへんは問題ないのですか?

    2011年2月27日 15:40
  • SurferOnWww様

    はじめまして、
    ご返答ありがとうございます。

    asp.net 2008, asp.net 2010は、
    Microsoft Visual Studio 2008/2010の中のasp.netを省略して書きました。
    意味が伝わらず、大変申し訳ありません。

    そうですね。Web.Configには変更ありますね。
    もちろん、Framework4.0用に変更しています。
    変更内容に問題があれば動作しないと思いますので、
    設定は問題ないと思っています。
    IIS側は、アプリケーションプールを、ASP.NET v4.0に変更しただけです。

    ただ、GridViewとは直接関係するとは考えられないのですが・・・

    hatukie



    2011年2月28日 4:49
  • > ただ、GridViewとは直接関係するとは考えられないのですが・・・

    この根拠は?

    http://msdn.microsoft.com/ja-jp/library/s57a598e.aspx?appId=Dev10IDEF1&l=JA-JP&k=k(VS.AMBIENT);k(TargetFrameworkMoniker-"SILVERLIGHT&k=VERSION=V3.0")&rd=true#aspnet_web_forms

    上記ページをみると、ASP.NET 4でWeb Formのコントロールは基本的なレベル(Controlクラスのレベル)から手が入っていることがわかります。
    GridViewだと「データコントロールの行選択の持続」の項目ではっきりコントロールの動作がいままでのバージョンと変わっているところがある、というのが述べられています。

    .NET Framework 2から3、3.5まではベースとなるランタイムが同じで、dllの追加、といったバージョンアップだったので、コントロールの挙動も大きく変わることはありませんでしたが、4ではランタイムも別で各種コントロールも別のものとして用意されていますから、まず違うことを前提に考えたほうがいいと思います。

    #あ、アセンブリのバージョンの話しようと思ったら、C:\Windows\assembly には3.5までのアセンブリしかないんだった。
     4になってどこにいったか、って誰のBlogに書いてあったんだっけかな。。。
     まあ、アセンブリの場所が違うほどバージョンアップで異なってます、ってことで(w


    あおい情報システム株式会社 小野修司(どっとねっとふぁん)
    • 回答としてマーク 山本春海 2011年3月18日 8:27
    2011年2月28日 8:38
  • 小野様

    はじめまして、
    ご返答ありがとうございます。

    >> ただ、GridViewとは直接関係するとは考えられないのですが・・・
    >この根拠は?

    Web.configとIISの設定で、GridViewに対しての設定ではないため、
    影響されることは考えられないということで、
    もちろん、設定の影響で.Net Framework4.0に変更されるため、
    その影響は考えられるという意味です。

    言葉足らずで申し訳ありません。

    教えていただいたページですと、
    確かに選択行について仕様が変更されているので、動作が異なる点では、間違いないですね。
    情報を提供して頂いてありがとうございます。

    今回、機能的にあまり変更点はないだろうと、
    甘く見て安易にバージョンアップしてしまいました。

    今後、気をつけて確認するように致します。
    貴重な情報本当にありがとうございました。

    hatukie

     

    2011年3月1日 7:08
  • 今さらながらのレスですが・・・

    > grdChildのRowCommandが発生した後、
    > grdParentのRowCommandが発生しますが、

    当方でも検証してみましたが、こちらは再現できました。

    ASP.NET 3.5 と ASP.NET 4 の GridView コントロールの仕様(?)の違いのよう
    です。

    ただし、子の GridView のボタンの CommandName を Select とか Cancel など組
    み込み機能を呼び出すための名前にしておくと、子の GridView のボタンクリック
    で親の GridView の RowCommand イベントは発生しないようです。

    > grdParent_RowCommand内では、
    > CommandArgumentの値は、btnTestParentButtonに設定してある値で、
    > CommandNameの値は、btnTestChildButtonの値として渡っておりました。

    こちらは再現できませんでした。

    子の GridView のボタンクリックで、親の GridView の RowCommand イベントが発
    生しますが、ハンドラに引数として渡される GridViewCommandEventArgs オブジェ
    クトの CommandName, CommandArgument プロパティ値は、子の GridView のボタン
    に設定したものになるはずです。

    検証に使ったコードを以下にアップしておきますので、確認してみてください。デ
    ータベースは Microsoft が提供しているサンプルデータベースの Northwind を使
    用しました。


    <%@ Page Language="C#" %>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <script runat="server">

        int n = 0;
        protected void SqlDataSource2_Selecting(object sender, SqlDataSourceSelectingEventArgs e)
        {
            e.Command.Parameters["@CustomerID"].Value =
                (string)GridView1.DataKeys[n].Value;
            n++;
        }

        protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
        {
            Label1.Text =
                ((GridView)sender).ID +", " + e.CommandName + ", " +
                e.CommandArgument.ToString() + "<br />";
        }


        protected void GridView2_RowCommand(object sender, GridViewCommandEventArgs e)
        {
            Label2.Text =
                ((GridView)sender).ID + ", " + e.CommandName +  ", " +
                e.CommandArgument.ToString();
        }
    </script>

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head id="Head1" runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
            <asp:Label ID="Label1" runat="server"></asp:Label>
            <asp:Label ID="Label2" runat="server"></asp:Label>

            <asp:SqlDataSource ID="SqlDataSource1"
                runat="server"
                ConnectionString="<%$ ConnectionStrings:Northwind %>"
                SelectCommand="SELECT TOP 10 [CustomerID] FROM [Customers]">
            </asp:SqlDataSource>

            <asp:SqlDataSource ID="SqlDataSource2"
                runat="server"
                ConnectionString="<%$ ConnectionStrings:Northwind %>"
                SelectCommand="SELECT TOP 5 [OrderID], [OrderDate], [Freight]
                               FROM [Orders]
                               WHERE ([CustomerID] = @CustomerID)"
                OnSelecting="SqlDataSource2_Selecting">
                <SelectParameters>
                    <asp:Parameter Name="CustomerID" Type="String" />
                </SelectParameters>
            </asp:SqlDataSource>

            <asp:GridView ID="GridView1"
                runat="server"
                AutoGenerateColumns="False"
                DataKeyNames="CustomerID"
                DataSourceID="SqlDataSource1"
                OnRowCommand="GridView1_RowCommand">
                <Columns>
                    <asp:TemplateField HeaderText="選択" ShowHeader="False">
                        <ItemTemplate>
                            <asp:Button ID="Button1"
                                runat="server"
                                CommandName="Parent"
                                CommandArgument='<%# Eval("CustomerID") %>'
                                Text="選択" />
                        </ItemTemplate>
                    </asp:TemplateField>
                    <asp:BoundField
                        DataField="CustomerID"
                        HeaderText="CustomerID" />
                    <asp:TemplateField HeaderText="Order Details">
                        <ItemTemplate>
                            <asp:GridView ID="GridView2"
                                runat="server"
                                AutoGenerateColumns="False"
                                DataKeyNames="OrderID"
                                DataSourceID="SqlDataSource2"
                                OnRowCommand="GridView2_RowCommand">
                                <Columns>
                                    <asp:BoundField
                                        DataField="OrderID"
                                        HeaderText="OrderID"
                                        InsertVisible="False"
                                        ReadOnly="True"
                                        SortExpression="OrderID" />
                                    <asp:BoundField
                                        DataField="OrderDate"
                                        HeaderText="OrderDate"
                                        SortExpression="OrderDate"
                                        DataFormatString="{0:yyyy/MM/dd}" />
                                    <asp:BoundField
                                        DataField="Freight"
                                        HeaderText="Freight"
                                        SortExpression="Freight"
                                        DataFormatString="${0:N2}"/>
                                    <asp:TemplateField HeaderText="選択" ShowHeader="False">
                                        <ItemTemplate>
                                            <asp:Button ID="Button2"
                                                runat="server"
                                                CommandName="Child"
                                                CommandArgument='<%# Eval("OrderID") %>'
                                                Text="選択" />
                                        </ItemTemplate>
                                    </asp:TemplateField>
                                </Columns>
                            </asp:GridView>
                        </ItemTemplate>
                    </asp:TemplateField>
                </Columns>
            </asp:GridView>
         </form>
    </body>
    </html>


    以下、今回の問題とは関係ないことですが・・・

    > asp.net 2008, asp.net 2010は、
    > Microsoft Visual Studio 2008/2010の中のasp.netを省略して書きました。

    その言い方は正しくなくて、正しい言い方は ASP.NET 3.5 とか ASP.NET 4
    だと思いますが、いかがですか?

    開発サーバーを利用しているのでなければ、開発環境のバージョンの違いは
    今回の話とは何も関係ないです。関係があるのは .NET Framework のバージ
    ョンの違いです。

    Visual Studio 2010 を使っても、最初に「新しいプロジェクト」または「新
    しい Web サイト」を作るときに、.NET Framework のバージョンを Visual
    Studio 2008 と同じにすれば、結果は同じになるはずです。

    • 回答としてマーク 山本春海 2011年3月18日 8:27
    2011年3月6日 5:31