Gridview为什么所有可见行都设置为脏?

时间:2011-04-29 20:14:35

标签: c# asp.net gridview sqldatasource

我正在使用BulkEditGridView控件,如http://roohit.com/site/showArc.php?shid=bbb62所述,它非常适合我的需求。我遇到的问题是每当我保存时,每个可见的行(我启用了分页)都会得到更新。单步执行代码,我看到grid.DirtyRows.Count等于单击保存按钮时每页的项数减去1。

我无法找到将行设置为脏的位置。我可以看看哪些建议?

我的代码隐藏只有这个:

using System;
using System.Web.UI.WebControls;
using System.Collections.Generic;
using System.Collections;
using System.Data.Common;

public partial class MSDS_MSDS_Admin_GridUpdate : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            gridMSDS.DataKeyNames = new String[] { "id" };
            gridMSDS.DataBind();
        }
    }
}

编辑:这是aspx代码。

<%@ Page Language="C#" MasterPageFile="~/MSDS/MSDS.master" AutoEventWireup="true" EnableEventValidation="false" CodeFile="GridUpdate.aspx.cs" Inherits="MSDS_MSDS_Admin_GridUpdate" Title="Untitled Page" %>

<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" %>
<%@ Register Assembly="RealWorld.Grids" Namespace="RealWorld.Grids" TagPrefix="cc2" %>
<asp:Content ID="Content1" ContentPlaceHolderID="PageContent" runat="Server">
    <br />
    <asp:Button ID="btnSave" runat="server" Text="Save" Width="100%" />
    <cc2:BulkEditGridView ID="gridMSDS" runat="server" AllowPaging="True" AllowSorting="True"
        DataSourceID="sqlData" EnableInsert="False" InsertRowCount="1" PageSize="20"
        SaveButtonID="btnSave" AutoGenerateColumns="False">
        <Columns>
            <asp:BoundField DataField="ID" HeaderText="ID" InsertVisible="False" Visible="false"
                ReadOnly="True" SortExpression="ID" />
            <asp:BoundField DataField="ChemicalTitle" HeaderText="ChemicalTitle" SortExpression="ChemicalTitle" />
            <asp:TemplateField HeaderText="SheetDate" SortExpression="SheetDate">
                <EditItemTemplate>
                    <asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("SheetDate") %>' Width="85px"></asp:TextBox>
                    <cc1:CalendarExtender ID="TextBox1_CalendarExtender" runat="server" Enabled="True"
                        TargetControlID="TextBox1">
                    </cc1:CalendarExtender>
                </EditItemTemplate>
                <ItemTemplate>
                    <asp:Label ID="Label2" runat="server" Text='<%# Eval("SheetDate") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:BoundField DataField="Filename" HeaderText="Filename" SortExpression="Filename" />
            <asp:BoundField DataField="Manufacturer" HeaderText="Manufacturer" SortExpression="Manufacturer" />
            <asp:BoundField DataField="UsageDept" HeaderText="UsageDept" SortExpression="UsageDept" />
            <asp:TemplateField HeaderText="Notes" SortExpression="Notes">
                <EditItemTemplate>
                    <asp:TextBox ID="TextBox5" runat="server" Text='<%# Bind("Notes") %>' TextMode="MultiLine"></asp:TextBox>
                </EditItemTemplate>
                <ItemTemplate>
                    <asp:Label ID="Label6" runat="server" Text='<%# Bind("Notes") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Status" SortExpression="Status">
                <EditItemTemplate>
                    <asp:DropDownList ID="ddlStatus" runat="server" DataSourceID="sqlStatus" DataTextField="DisplayValue"
                        DataValueField="Value" SelectedValue='<%# Bind("Status") %>'>
                    </asp:DropDownList>
                    <asp:SqlDataSource ID="sqlStatus" runat="server" ConnectionString="<%$ ConnectionStrings:NCLWebConnectionString %>"
                        SelectCommand="getOptionList" SelectCommandType="StoredProcedure">
                        <SelectParameters>
                            <asp:Parameter DefaultValue="msds_Status" Name="ListName" Type="String" />
                        </SelectParameters>
                    </asp:SqlDataSource>
                </EditItemTemplate>
                <ItemTemplate>
                    <asp:DropDownList ID="ddlStatus" runat="server" DataSourceID="sqlStatus" disabled="true"
                        BackColor="White" DataTextField="DisplayValue" DataValueField="Value" SelectedValue='<%# Bind("Status") %>'>
                    </asp:DropDownList>
                    <asp:SqlDataSource ID="sqlStatus" runat="server" ConnectionString="<%$ ConnectionStrings:NCLWebConnectionString %>"
                        SelectCommand="getOptionList" SelectCommandType="StoredProcedure">
                        <SelectParameters>
                            <asp:Parameter DefaultValue="msds_Status" Name="ListName" Type="String" />
                        </SelectParameters>
                    </asp:SqlDataSource>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Health" SortExpression="Health">
                <EditItemTemplate>
                    <center>
                        <asp:TextBox ID="TextBox2" runat="server" Style="text-align: center" Text='<%# Bind("Health") %>'
                            Width="25px"></asp:TextBox>
                    </center>
                </EditItemTemplate>
                <ItemTemplate>
                    <asp:Label ID="Label3" runat="server" Text='<%# Bind("Health") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Fire" SortExpression="Fire">
                <EditItemTemplate>
                    <center>
                        <asp:TextBox ID="TextBox3" runat="server" Text='<%# Bind("Fire") %>' Width="25px"></asp:TextBox></center>
                </EditItemTemplate>
                <ItemTemplate>
                    <asp:Label ID="Label4" runat="server" Text='<%# Bind("Fire") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Reactivity" SortExpression="Reactivity">
                <EditItemTemplate>
                    <center>
                        <asp:TextBox ID="TextBox4" runat="server" Text='<%# Bind("Reactivity") %>' Width="25px"></asp:TextBox></center>
                </EditItemTemplate>
                <ItemTemplate>
                    <asp:Label ID="Label5" runat="server" Text='<%# Bind("Reactivity") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:BoundField DataField="DateUpdated" HeaderText="DateUpdated" SortExpression="DateUpdated"
                ReadOnly="True" />
            <asp:BoundField DataField="UpdatedBy" ReadOnly="True" HeaderText="UpdatedBy" SortExpression="UpdatedBy" />
        </Columns>
    </cc2:BulkEditGridView>
    <asp:SqlDataSource ID="sqlData" runat="server" ConnectionString="<%$ ConnectionStrings:NCLWebConnectionString %>"
        SelectCommand="SELECT [ID], [ChemicalTitle], dbo.dateOnly([SheetDate]) As [SheetDate], [Filename], [Manufacturer], [UsageDept], [Notes], isnull([Status], 4) as [Status], [Health], [Fire], [Reactivity], [DateUpdated], [UpdatedBy] FROM [msds_Sheets] ORDER BY [ChemicalTitle]"
        UpdateCommand="msds_UpdateSheet" UpdateCommandType="StoredProcedure">
        <UpdateParameters>
            <asp:Parameter Name="ID" Type="Int32" />
            <asp:Parameter Name="ChemicalTitle" Type="String" />
            <asp:Parameter Name="SheetDate" DbType="DateTime" />
            <asp:Parameter Name="Filename" Type="String" />
            <asp:Parameter Name="Manufacturer" Type="String" />
            <asp:Parameter Name="UsageDept" Type="String" />
            <asp:Parameter Name="Notes" Type="String" />
            <asp:Parameter Name="Status" Type="Int16" />
            <asp:Parameter Name="Health" Type="Int16" />
            <asp:Parameter Name="Fire" Type="Int16" />
            <asp:Parameter Name="Reactivity" Type="Int16" />
            <asp:ProfileParameter Name="UpdatedBy" Type="String" PropertyName="Username" />
        </UpdateParameters>
    </asp:SqlDataSource>
</asp:Content>

测试程序如下:
- 加载页面。
- 在第一行编辑内容 - 点击保存按钮。

2 个答案:

答案 0 :(得分:4)

您发布的代码看起来不错。我的测试代码与您的测试代码几乎相同,但我无法产生您看到的不需要的结果。

您的代码和我的代码之间最显着的区别是我没有母版页的代码。我的母版页是VS 2008创建的默认页面。除此之外,差异在于SQL和底层数据库。具体来说,我没有使用任何存储过程,并且我对所涉及的数据类型做出了合理的假设:IDintStatussmallint,{{1 } {是SheetDateDateDateUpdated,其他所有内容都是DateTime

编辑:您的varchar似乎只是数据库中基础SheetDate值的日期部分。您的查询为了显示目的而转换基础数据值这一事实并不重要,因为网格视图无法判断它是否获得了修改后的值。 END OF EDIT

以下是诊断问题的一些建议:

  • 在没有母版页或没有母版页的情况下进行测试 非常简单的虚拟母版页 保证没有脚本 与DateTime互动。 由于BulkEditGridView是 显然在你的母版页上,你会的 需要移动脚本 管理员控制页面本身, 或者暂时摆脱 ToolkitScriptManager元素,哪个 需要脚本管理器。

  • 暂时替换CalendarExtender 带有绑定数据的模板字段 领域,消除可能性 与Status的互动。 下拉列表没有导致 我的测试中存在问题,但可能存在问题 是你的微妙差异 代码和我的。

  • 如果这些都没有帮助,那么可能的原因就是你的问题 版本DropDownList

编辑 - 其他诊断建议:

  • 根据对BulkEditGridView源代码的检查,似乎代码正确跟踪网格的哪些行是“脏”的。因此,虚假脏行的最可能原因是网格中的一个或多个控件错误地检测到其数据内容的更改。您可以使用BulkEditGridView的源代码而不是预编译的DLL在调试器中检测到这一点。

  • BulkEditGridView的开头设置断点,该事件处理程序检测网格任何单元格中的更改。通过检查调试器中该对象的HandleRowChanged参数,您可以确定网格中的哪些控件正在进行值更改。特别是,您将能够分辨哪些控件(如果有)错误地触发了值更改事件。

  • 一旦确定哪些控件错误地报告其值已发生变化,您就可以专注于为什么这种情况发生。

END OF EDIT

其他一些改进代码的建议如下。 这些不会解决原始问题,但会使代码更清晰:

  • 在所有模板字段中,删除sender。它们永远不会被使用,因为ItemTemplate强制每一行都处于编辑状态。

  • 在后面的代码中,BulkEditGridView 从源头开始,不需要呼叫 数据在声明中指定 标记,因此是网格视图 控件会自动绑定 数据

答案 1 :(得分:0)

我不是BulkEditGridView控件的专家,但这是我在Matt Dotson的blog entry

中找到的

除非您明确注意更改,否则您可能无法知道该行已更新。首先,为每一行添加一个更改处理程序

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);
         }
      }
   }

然后定义脏行列表并添加需要在那里更新的行(在事件处理程序中)

   private List<int> dirtyRows = new List<int>();
   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();
   }

这是你的ASPX代码

<asp:Button runat="server" ID="SaveButton" Text="Save Data" />
   <blog:BulkEditGridView runat="server" id="EditableGrid" DataSourceID="AdventureWorks" AutoGenerateColumns="False" DataKeyNames="LocationID" SaveButtonID="SaveButton" >
      <Columns>
         <asp:BoundField DataField="LocationID" HeaderText="LocationID" InsertVisible="False" ReadOnly="True" SortExpression="LocationID" />
         <asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
         <asp:BoundField DataField="Availability" HeaderText="Availability" SortExpression="Availability" />
         <asp:BoundField DataField="CostRate" HeaderText="CostRate" SortExpression="CostRate" />
      </Columns>
   </blog:BulkEditGridView>