GridView.Datasource为null - 寻找替代解决方案

时间:2009-12-10 15:15:51

标签: c# asp.net gridview datasource

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

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

我绑定了代码中的所有控件。我在声明性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();
}

到目前为止,这么好。显示所有内容,包括我的PhoneNumbers网格(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网格视图,它必须绑定到formview数据源中的一个“子值”。

是否可以将formview中的gridview绑定到formview数据源的数据子集?如果是这样,如何以声明方式定义?

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

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

一些想法。

在DataBind GridView之前,你要检查是否(!PostBack),以免你在GridView中过度写入数据。

保存逻辑应位于保存按钮的OnClick事件中。不在Page_Load中(如果已经在那里)。