2

I can't figure out how to use model binding in web forms to populate a child collection of a view model. Suppose I have the following:

public class MeasurementViewModel
{
  public string Name {get;set;}
  public int MeasurementTypeId {get;set;}
  public double Value {get;set;}
}
public class ExperimentViewModel
{
  public bool ExperimentAorB {get;set;}
  public List<MeasurementViewModel> Measurements {get;set;}
}

So there are two types of experiments, A or B, each of which require a different set of measurements. I'd like to do this all on one page so that the user selects the experiment type, and is then presented with the list of measurements to enter via simple text boxes. This is simple in MVC, but I'm stuck with web forms where it's not clear how to do this.

<asp:DropDownList ID="ddExperiment" runat="server" CssClass="form-control" AutoPostBack="true"
   DataValueField="Id" DataTextField="Description"
   SelectMethod="ddPartCode_GetData" />
<asp:FormView ID="Entry" RenderOuterTable="false" runat="server" DefaultMode="Insert" Visible="<%# !string.IsNullOrEmpty(ddExperiment.SelectedValue) %>"
   ItemType="ExperimentViewModel" SelectMethod="Entry_GetItem" InsertMethod="Entry_InsertItem">
   <EditItemTemplate>
     <asp:TextBox ID="txtName" Text="<%# BindItem.Name %>" runat="server" />
     <!-- ??? -->
   </EditItemTemplate>
</asp:FormView>

The insert method of the FormView is like this:

public void Entry_InsertItem(ExperimentViewModel item)

I've tried various markup in the ??? section, like a ListView with a SelectMethod with this signature:

public IEnumerable<MeasurementViewModel> Measurements_GetData(
    [Control("ddExperiment")] int experimentType) ...

That works to display the proper form, but on postback ExperimentViewModel.Measurements is always null. I've also tried insert methods on the list view and a repeater to no avail.

I can obviously do this manually, but I figured there must be a standard way to do this using model binding. Obviously I have to define a control that actually binds to the ExperimentViewModel.Measurements, but I'm not sure how to do that in this setup.

naasking
  • 2,514
  • 1
  • 27
  • 32
  • Same solution as posted here applies: http://stackoverflow.com/questions/36804682/web-forms-model-binding-child-collection – naasking Jan 18 '17 at 15:50

1 Answers1

0

You can bind a child ListView by using DataSource="<%# Item.Measurements %>. Here is an example:

<asp:FormView ID="FormView" runat="server" RenderOuterTable="false" ItemType="ExperimentViewModel" DataKeyNames="Id" DefaultMode="Edit" SelectMethod="FormView_GetItem" UpdateMethod="FormView_UpdateItem">
        <EmptyDataTemplate>
            The record you requested does not exist.
        </EmptyDataTemplate>
        <EditItemTemplate>
        <asp:ListView ID="ListView" runat="server" ItemType="MeasurementViewModel" DataKeyNames="Id" DataSource="<%# Item.Measurements %>">
        ...
        </asp:ListView> 
    </EditItemTemplate>
</asp:FormView>

I'm not positive that the values will be populated on postback. You may have to repopulate the model in the insert method. I'm not sure exactly what you are trying to do in the child template. Hope this helps.

John
  • 772
  • 7
  • 17
  • Populating the child collection on postback is the problem. What you suggested doesn't work, nor does using SelectMethod on the nested ListView. Consider an ExperimentEntryForm, where you select the type of experiment, and are given a list of measurements (key-value pairs) for that type of experiment. How would you represent this using web forms model binding such that ExperimentViewModel.Measurements is populated on the FormView update event? There is currently no answer: http://stackoverflow.com/questions/21667583/asp-net-web-forms-4-5-model-binding-where-the-model-contains-a-collection – naasking Apr 27 '16 at 13:51