【问题标题】:GridView.Datasource is null - looking for alternative solutionGridView.Datasource 为空 - 寻找替代解决方案
【发布时间】:2009-12-10 15:15:51
【问题描述】:

我有一个 Person 类,其中包含 FirstName、LastName、EmployeeID 等属性。所有上述属性都只是单个字符串。 Person 类还有一些属性,这些属性是我定义的其他对象的列表。 例如,Person 对象有一个名为“PhoneNumbers”的属性,即List<PersonPhoneNumbers>。 PersonPhoneNumbers 是一个包含 Number、Extension、Type 等基本属性的类。

现在,我有一个用于编辑 Person 对象的 Web 表单。它包含所有基本 Person 属性的文本字段,以及用于显示 List<T> 类型的属性的网格视图。

我在后面的代码中绑定了所有的控件。我在声明性 aspx 页面中没有数据源控件。

在后面的代码中,我有一个名为“_myPerson”的私有变量,它的类型为“Person”。当页面首次加载时,它会检查 QueryString 中的“ID”值,如果存在,则使用该值实例化“_myPerson”对象。此过程将进入数据库并获取数据并填充“_myPerson”对象的所有属性。

然后我调用一个名为“LoadFormControlsFromPerson()”的方法来设置所有表单域的值。 这是那个方法:

/// <summary>
/// Fills the form controls from the data in the Person object.
/// </summary>
private void LoadFormControlsFromPerson()
{
    // Fill Data
    txtFirstName.Text = myPerson.FirstName;
    txtMiddleName.Text = myPerson.MiddleName;
    txtLastName.Text = myPerson.LastName;
    txtEmployeeID.Text = myPerson.EmployeeID;

    if (myPerson.SOMRelationshipType.Id != CommonBase.Int_NullValue)
    {
        ddlSOMRelationshipType.SelectedValue = myPerson.SOMRelationshipType.Id.ToString();
    }
    else
    {
        ddlSOMRelationshipType.SelectedIndex = 0;
    }
    cbDisabledFlg.Checked = myPerson.DisabledFlg;

    if (!myPerson.IsNew)
    {
        lblSidePanelID.Text = myPerson.Id.ToString();
        lblSidePanelName.Text = myPerson.FirstName + " " + myPerson.LastName;
    }

    gvPhoneNumbers.DataSource = myPerson.PhoneNumbers;
    gvPhoneNumbers.DataBind();

    SetFormControlsUsability();
}

到目前为止,一切都很好。一切都会显示,包括我的电话号码网格(gvPhoneNumbers)。 gridview定义如下:

<asp:GridView ID="gvPhoneNumbers" runat="server" 
                    AutoGenerateColumns="false" DataKeyNames="ID" >
                    <Columns>
                        <asp:TemplateField>
                            <ItemTemplate>
                                <asp:LinkButton ID="btnEditPhoneNumber" runat="server" Text="Edit" CommandName="Select" />
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:BoundField DataField="Number" HeaderText="Number" />
                        <asp:BoundField DataField="Extension" HeaderText="Extension" />
                        <asp:BoundField DataField="CountryCode" HeaderText="CountryCode" />
                        <asp:TemplateField HeaderText="Type">
                             <ItemTemplate>
                                 <asp:Label ID="lblPersonPhoneNumberRelationshipType" runat="server" Text='<%# Bind("RelationshipType.Name") %>'></asp:Label>
                             </ItemTemplate>
                        </asp:TemplateField>
                        <asp:CheckBoxField DataField="PrimaryFLG" HeaderText="Primary" />
                    </Columns>
                    </asp:GridView>

当用户单击“保存”时,另一个名为“LoadPersonFromFormControls”的方法会使用来自表单控件的数据填充一个 Person 对象。这是那个方法:

/// <summary>
/// Updates a passed Person object with data from the form controls.
/// </summary>
private void LoadPersonFromFormControls(Person passedPerson)
{
    passedPerson.FirstName = txtFirstName.Text.Trim();
    passedPerson.MiddleName = txtMiddleName.Text.Trim();
    passedPerson.LastName = txtLastName.Text.Trim();
    passedPerson.EmployeeID = txtEmployeeID.Text.Trim();
    passedPerson.SOMRelationshipType = LookupCodeManager.GetItem(int.Parse(ddlSOMRelationshipType.SelectedValue));
    passedPerson.DisabledFlg = cbDisabledFlg.Checked;
    passedPerson.PhoneNumbers = (EquatableList<PersonPhoneNumber>)gvPhoneNumbers.DataSource;
}

问题是回发后“gvPhoneNumbers.DataSource”为空。经过一些在线阅读,据我了解,Gridview 不会自动“缓存”它的数据集,并且回发后无法引用它的能力是不可能的,除非开发人员在会话或视图状态或某种机制中有意保存/缓存数据那个。

现在,我知道如果我在 aspx 页面中以声明方式创建了 objectdatasource,gridview 会记住它的数据。我最初没有这样做的原因是因为我不想获得两次数据。一次是在第一次实例化 person 对象时的代码中,第二次是在触发 objectdatasource 时。

所以我现在正在考虑仅在 aspx 页面中移动到 objectdatasource,而不是在代码隐藏中设置值。我在想我会为整个 Person 对象创建一个对象数据源,然后将 formview 绑定到它。 formview 内部是我的 gvPhoneNumber gridview,它必须绑定到 formview 数据源中的“子值”之一。

是否可以将表单视图中的网格视图绑定到表单视图数据源中的数据子集?如果是这样,它是如何以声明方式定义的?

另外,你认为走这条路值得吗?有没有人有解决这个问题的其他建议?我不想每次页面加载都检索相同的数据两次。

【问题讨论】:

  • 好吧,我尝试在回发后遍历 Gridview 的每一行并从中创建一个数据集,但回发后 Gridview.Rows 始终为空。我确保我有所有的视图状态,但仍然没有运气。最后,我最终将 Person.PhoneNumbers 列表保存在我的应用程序缓存中,并在回发后更新它,然后重新绑定 gridview。到目前为止似乎工作。而且没有声明性数据源!

标签: c# asp.net gridview datasource


【解决方案1】:

当页面回发时,您可以从网格行和网格单元格中检索数据,对吗?然后使用它们重新创建数据集或更新数据库。所以需要在数据集中存储主键。

【讨论】:

  • 我最近也这样做了,所以我可以确认一下。您必须确保 GridView 控件的 EnableViewState 已打开,否则您将处理回发时设置的空行。
  • 我将 EnableViewState 设置为 true,但回发时 GridView.Rows 计数始终为零。还有其他想法吗?
【解决方案2】:

一些想法。

在你 DataBind GridView 之前,你要检查 if(!PostBack) 这样你就不会在 GridView 中覆盖数据。

保存 逻辑应该在保存按钮的 OnClick 事件中。不在 Page_Load 中(如果它已经存在的话)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-04
    • 2012-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-09
    • 1970-01-01
    • 2011-11-14
    相关资源
    最近更新 更多