I have a Person class that contains properties such a FirstName, LastName, EmployeeID, etc. All of the aforementioned properties are just single strings. The Person class also has some properties that are lists of other objects I have defined.
For instance, the Person object has a property called "PhoneNumbers" which is a List<PersonPhoneNumbers>
. PersonPhoneNumbers is a class that contains basic properties such as Number, Extension, Type.
Now, I have a web form for editing the Person object. It contains text fields for all of the basic Person properties, and gridviews for displaying the properties that are List<T>
types.
I bind all the controls in the code behind. I have no datasource controls in the declarative aspx page.
In the code behind I have a private variable called "_myPerson" that is of type "Person". When the page first loads, it checks the QueryString for an "ID" value and if it exists, it instantiates the "_myPerson" object with that value. This process will go to the database and get the data and populate all the properties of the "_myPerson" object.
I then call a method named "LoadFormControlsFromPerson()" that sets the values for all the form fields. Here is that method:
/// <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();
}
So far, so good. Everything displays, including my grid of PhoneNumbers (gvPhoneNumbers). The gridview is defined as follows:
<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>
When I the user clicks on "Save", another method named "LoadPersonFromFormControls" populates a Person object with the data from the form controls. Here is that method:
/// <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;
}
The problem is that "gvPhoneNumbers.DataSource" is null after postback. After some online reading, it is my understanding that the Gridview does not automatically "cache" it's dataset and the ability to reference it after postback is not possible unless the data is intentionally saved/cached by the developer in session or viewstate or some mechanism like that.
Now, I know that the gridview will remember it's data if I created an objectdatasource declaratively in the aspx page. The reason I didn't do that in the first place was because I didn't want to be getting the data twice; once in the code behind when the person Object was first instantiated and a second time when the objectdatasource fired.
So I am now considering moving to an objectdatasource only in the aspx page, and not setting the values in the codebehind at all. I was thinking I would make an object datasource for the entire Person object, and then bind a formview to it. Inside the formview would be my gvPhoneNumber gridview, which would have to be bound to one of the "sub values" inside the formview's datasource.
Is it possible to bind a gridview inside a formview to a subset of data from the formview's datasource? If so, how is that defined declaratively?
Also, do you think that going this route is worth it? Does anyone have other suggestions for solving this problem? I don't want to be retreiving the same data twice for each page load.