2009-12-10 91 views
1

我有一个Person类,其中包含诸如FirstName,LastName,EmployeeID等属性。所有上述属性都只是单个字符串。 Person类还有一些属性是我定义的其他对象的列表。 例如,Person对象有一个名为“PhoneNumbers”的属性,它是List<PersonPhoneNumbers>。 PersonPhoneNumbers是一个包含基本属性的类,例如Number,Extension,Type。GridView.Datasource为空 - 寻找替代解决方案

现在,我有一个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会记住它的数据。我之所以没有这么做是因为我不想两次获取数据;一次在代码背后的人物对象第一次实例化和第二次当objectdatasource被解雇时。

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

是否有可能将formview中的gridview绑定到formview的数据源的数据子集?如果是这样,那么声明如何定义?

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

+0

嗯,我试图在回发之后遍历Gridview的每一行,并从中创建数据集,但Gridview.Rows在回发后总是空的。我确信我已经查看了所有内容,但仍然没有运气。最后,我最终将Person.PhoneNumbers列表保存在我的应用程序缓存中,并在回发后更新它,然后重新绑定gridview。似乎工作到目前为止。并没有声明数据源! – 2009-12-10 16:35:54

回答

1

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

+0

我最近也做了这个,所以我可以证实这一点。您必须确保为'GridView'控件启用'EnableViewState',否则您将在回发时处理空行集。 – Codesleuth 2009-12-10 15:40:57

+0

我将EnableViewState设置为true,但GridView.Rows计数在回发时始终为零。任何其他想法? – 2009-12-10 15:50:24

0

几个想法。

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

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