5

以下のリンクからコピーして貼り付けるだけで、一括編集可能なグリッドビュー Web ユーザー コントロール ( BulkEditGridView.ascx) を作成しました。外部コードは含まれていません。

http://blogs.msdn.com/b/mattdotson/archive/2005/11/09/real-world-gridview-bulk-editing.aspx

BulkEditGridView コントロールを別の Web ユーザー コントロールOrderDetailGridView.ascxに追加し、データソースを BulkEditGridView に追加しました

私がやろうとしているのは、BulkEditGridView 内に相互に依存するドロップダウン リストと 2 つのテキスト ボックスを用意することです。(OrderDetailGridView.ascx ソース コードを参照) ドロップダウン リストが変更された時点で、テキスト ボックスは変更されず、保存ボタンをクリックすると、対応する値が更新され、テキスト ボックスに表示されます。

ただし、ドロップダウンリストが変更されたときに、保存ボタンをクリックする前に、テキストボックス内の対応する値を確認し、保存ボタンで保存できるようにしたいのです。

autpostback=true と ddl_MaterialCode_SelectedIndexChanged イベントを設定してテキスト ボックスを変更しようとしましたが、保存ボタンが機能しません。

updatepanel を配置しようとしましたが、やはり同じで、保存ボタンが機能しませんでした。

以下は、保存をクリックした後にテキストボックスが更新された場所で保存ボタンが機能する私のコードのソースコードです。

BulkEditGridView.ascx ソース コード (自分で何も追加せず、コピーして貼り付けるだけです):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Exportal.Controls 
{
    public partial class BulkEditGridView : System.Web.UI.WebControls.GridView
    {


        private List<int> dirtyRows = new List<int>();

        [IDReferenceProperty(typeof(Control))]
        public string SaveButtonID
        {
            get
            {
                string val = (string)this.ViewState["SaveButtonID"];
                if (val == null)
                {
                    return string.Empty;
                }
                return val;
            }
            set
            {
                this.ViewState["SaveButtonID"] = value;
            }
        }

        protected override GridViewRow CreateRow(int rowIndex, int dataSourceIndex, DataControlRowType rowType, DataControlRowState rowState)
        {
            return base.CreateRow(rowIndex, dataSourceIndex, rowType, rowState | DataControlRowState.Edit);
        }

        protected override void OnLoad(EventArgs e)
        {

            base.OnLoad(e);

            //Attach an event handler to the save button.
            if (false == string.IsNullOrEmpty(this.SaveButtonID))
            {
                Control btn = RecursiveFindControl(this.NamingContainer, this.SaveButtonID);
                if (null != btn)
                {
                    if (btn is Button)
                    {
                        ((Button)btn).Click += new EventHandler(SaveClicked);
                    }
                }
            }

        }
        private void SaveClicked(object sender, EventArgs e)
        {
            this.Save();
            this.DataBind();
        }

        protected override void InitializeRow(GridViewRow row, DataControlField[] fields)
        {
            base.InitializeRow(row, fields);
            foreach (DataControlFieldCell cell in row.Cells)
            {
                if (cell.Controls.Count > 0)
                {
                    AddChangedHandlers(cell.Controls);
                }
            }
        }

        private void AddChangedHandlers(ControlCollection controls)
        {
            foreach (Control ctrl in controls)
            {
                if (ctrl is TextBox)
                {
                    ((TextBox)ctrl).TextChanged += new EventHandler(this.HandleRowChanged);
                }
                else if (ctrl is CheckBox)
                {
                    ((CheckBox)ctrl).CheckedChanged += new EventHandler(this.HandleRowChanged);
                }
                else if (ctrl is DropDownList)
                {
                    ((DropDownList)ctrl).SelectedIndexChanged += new EventHandler(this.HandleRowChanged);
                }
            }
        }

        void HandleRowChanged(object sender, EventArgs args)
        {
            GridViewRow row = ((Control)sender).NamingContainer as GridViewRow;
            if (null != row && !dirtyRows.Contains(row.RowIndex))
            {
                dirtyRows.Add(row.RowIndex);
            }
        }
        public void Save()
        {
            foreach (int row in dirtyRows)
            {
                this.UpdateRow(row, false);
            }

            dirtyRows.Clear();
        }
        private Control RecursiveFindControl(Control namingcontainer, string controlName)
        {
            Control c = namingcontainer.FindControl(controlName);

            if (c != null)
                return c;

            if (namingcontainer.NamingContainer != null)
                return RecursiveFindControl(namingcontainer.NamingContainer, controlName);

            return null;
        }
    }
}

OrderDetailGridView.ascx ソース コード:

<cc1:BulkEditGridView ID="BulkEditGridView1" runat="server" AutoGenerateColumns="False"
    DataKeyNames="RowNo" DataSourceID="SqlDataSource1" SaveButtonID="btn_Kaydet">
    <Columns>
        <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
        <asp:BoundField DataField="PONumber" HeaderText="PONumber" SortExpression="PONumber" />
        <asp:TemplateField HeaderText="MaterialCode" SortExpression="MaterialCode">
            <EditItemTemplate>
                <asp:DropDownList ID="ddl_MaterialCode" runat="server" DataSourceID="SqlDataSource2"
                    DataTextField="MaterialCode" DataValueField="MaterialCode" SelectedValue='<%# Bind("MaterialCode") %>'
                    OnSelectedIndexChanged="ddl_MaterialCode_SelectedIndexChanged" >
                </asp:DropDownList>
            </EditItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="MaterialDescription" SortExpression="MaterialDescription">
            <EditItemTemplate>
                <asp:TextBox ID="txt_MaterialDescription" runat="server" Text='<%# Bind("MaterialDescription") %>'
                    Enabled="false"></asp:TextBox>
            </EditItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="MaterialCategory" SortExpression="MaterialCategory">
            <EditItemTemplate>
                <asp:TextBox ID="txt_MaterialCategory" runat="server" Text='<%# Bind("MaterialCategory") %>'
                    Enabled="false"></asp:TextBox>
            </EditItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="UnitOfMeasure" HeaderText="UnitOfMeasure" SortExpression="UnitOfMeasure" />
        <asp:BoundField DataField="Quantity" HeaderText="Quantity" SortExpression="Quantity" />
        <asp:BoundField DataField="ContainerType" HeaderText="ContainerType" SortExpression="ContainerType" />
        <asp:BoundField DataField="LoadingDate" HeaderText="LoadingDate" SortExpression="LoadingDate" />
    </Columns>
</cc1:BulkEditGridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:MyDbConn %>"
    DeleteCommand="DELETE FROM [OrderDetail] WHERE [RowNo] = @RowNo" InsertCommand="INSERT INTO [OrderDetail] ([FileNo], [PONumber], [MaterialCode], [MaterialDescription], [MaterialCategory], [UnitOfMeasure], [Quantity], [ContainerType], [LoadingDate]) VALUES (@FileNo, @PONumber, @MaterialCode, @MaterialDescription, @MaterialCategory, @UnitOfMeasure, @Quantity, @ContainerType, @LoadingDate)"
    SelectCommand="SELECT * FROM [OrderDetail]" UpdateCommand="UPDATE [OrderDetail] SET [FileNo] = @FileNo, [PONumber] = @PONumber, [MaterialCode] = @MaterialCode, [MaterialDescription] = @MaterialDescription, [MaterialCategory] = @MaterialCategory, [UnitOfMeasure] = @UnitOfMeasure, [Quantity] = @Quantity, [ContainerType] = @ContainerType, [LoadingDate] = @LoadingDate WHERE [RowNo] = @RowNo">
    <DeleteParameters>
        <asp:Parameter Name="RowNo" Type="Int32" />
    </DeleteParameters>
    <InsertParameters>
        <asp:Parameter Name="FileNo" Type="Int32" />
        <asp:Parameter Name="PONumber" Type="String" />
        <asp:Parameter Name="MaterialCode" Type="String" />
        <asp:Parameter Name="MaterialDescription" Type="String" />
        <asp:Parameter Name="MaterialCategory" Type="String" />
        <asp:Parameter Name="UnitOfMeasure" Type="String" />
        <asp:Parameter Name="Quantity" Type="Int32" />
        <asp:Parameter Name="ContainerType" Type="String" />
        <asp:Parameter Name="LoadingDate" Type="String" />
    </InsertParameters>
    <UpdateParameters>
        <asp:Parameter Name="FileNo" Type="Int32" />
        <asp:Parameter Name="PONumber" Type="String" />
        <asp:Parameter Name="MaterialCode" Type="String" />
        <asp:Parameter Name="MaterialDescription" Type="String" />
        <asp:Parameter Name="MaterialCategory" Type="String" />
        <asp:Parameter Name="UnitOfMeasure" Type="String" />
        <asp:Parameter Name="Quantity" Type="Int32" />
        <asp:Parameter Name="ContainerType" Type="String" />
        <asp:Parameter Name="LoadingDate" Type="String" />
        <asp:Parameter Name="RowNo" Type="Int32" />
    </UpdateParameters>
</asp:SqlDataSource>
<asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:MyDbConn %>"
    SelectCommand="SELECT [MaterialCode] FROM [Materials]"></asp:SqlDataSource>
<asp:Button ID="btn_Kaydet" runat="server" Text="Save" />

OrderDetailGridView.ascx.cs ソース コード

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using SOrderDetailData;
using System.Data;

namespace Exportal.Controls
{
    public partial class OrderDetailGridView : System.Web.UI.UserControl
    {
        protected void ddl_MaterialCode_SelectedIndexChanged(object sender, EventArgs e)
        {

            DataTable dt = new DataTable();
            dt = OrderDetailData.GetMaterials();

            DropDownList ddl_MaterialCode = (DropDownList)sender;
            GridViewRow r = (GridViewRow)ddl_MaterialCode.Parent.Parent;

            TextBox txt_MaterialDescription = (TextBox)r.FindControl("txt_MaterialDescription");
            TextBox txt_MaterialCategory = (TextBox)r.FindControl("txt_MaterialCategory");            

            txt_MaterialDescription.Text = dt.Rows[ddl_MaterialCode.SelectedIndex]["MaterialDescription"].ToString();
            txt_MaterialCategory.Text = dt.Rows[ddl_MaterialCode.SelectedIndex]["MaterialCategory"].ToString();


        }
    }
}
4

4 に答える 4

1

試してみるべき2つのこと:以下のコードにブレークポイントを設定してデバッグします。アプリがこのbtnに到達していることを確認してください...

if (null != btn) {
    if (btn is Button) {
        ((Button)btn).Click += new EventHandler(SaveClicked);
    }
}

それを確認したら、このボタンをスクリプトマネージャーに追加する必要があります

if (null != btn) {
    if (btn is Button) {
        ((Button)btn).Click += new EventHandler(SaveClicked);
        ScriptManager.GetCurrent(Page).RegisterAsyncPostBackControl(btn);
    }
}

このコントロールはどういうわけかupdatepanel内にありますか(おそらくあなたのmastepageにはすべてのコンテンツのupdatepanelがあります)?

于 2012-08-13T20:24:54.373 に答える
1

List<int> dirtyRowsポストバックを生き残ることができるように、おそらく永続化する必要があります。Cacheまたはのいずれかをお勧めしますが、使用可能なすべてのオプションについては、SessionMSDN の記事ASP.NET アプリケーションで永続的なユーザー状態を管理するための 9 つのオプションを参照してください。

于 2012-08-10T07:53:18.047 に答える
1

ドロップダウンから選択した値をテキストボックスに入力するだけなら、jquery をお勧めします...

$('.dropdownclass').change(function() {
    $(this).closest('tr').find('.textboxclass').val($(this).val());
});

その後、追加のポストバックを行う必要はありません。ボタンのクリックが機能することを願っています。

于 2012-08-15T22:17:09.640 に答える
1

ドロップダウンから選択した値をテキストボックスに入力するだけの場合は、誰かが以前に書いたようなjqueryもお勧めします...

しかし、ドロップダウンが変更されたときにさらに何かを行う必要がある場合は、グリッドの RowCommand イベントを使用する必要があります。これはRowCommandを助けるかもしれません

ショートストーリー:

  1. OnRowCommand="myGrid_RowCommand" をグリッドのプロパティに追加します
  2. CommandName="ddlChanged" をグリッドのドロップダウンのプロパティに追加します
  3. グリッドのすべての行に複数のコマンドがある場合、myGrid_RowCommand 関数は次のようになります。

    void myGrid_RowCommand(Object sender, GridViewCommandEventArgs e)  {    
    if(e.CommandName=="ddlChanged") 
        {// Do something
        } 
    if(e.CommandName == "ddl2Changed")
        {// Do something else
        }
    ...
    }
    
于 2012-08-16T04:04:06.237 に答える