Question

I have a table called Field in my database and a table called FieldValue. My models look like this:

[Table("Field")]
public class Field
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int FieldId { get; set; }
    public string Value { get; set; }
}

[Table("FieldValue")]
public class FieldValue
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int FieldValueId { get; set; }
    public int FieldId { get; set; }
    public string Value { get; set; }
}

I would like to display each field as the label and then a textbox for each FieldValue associated with that Field but I'm not quite sure how to approach this. I am using MVC 4 if that matters.

Was it helpful?

Solution

You could return the joined array to a view model class (untested for syntax/typos):

public class ViewModel
{
    public KeyValuePair<string,string> Fields { get; set; }
}

var kvps = Fields.Join(FieldValues,
    f => f.FieldId,
    fv => fv.FieldId,
    (f, fv) => 
        new KeyValuePair<string,object>(f.Value, fv.Value)
    }).ToArray();
var viewModel = new ViewModel { Fields = kvps };

return View(viewModel);

Then in the view, simply iterate over the values:

@model MyNamespace.ViewModel

@foreach (var kvp in Model.Fields)
{
    <span class="field-label">@kvp.Key</span>
    <span class="field-value">@Html.TextBoxFor(_ => kvp.Value)</span>
}

If you put this in a form, then the postback should also work correctly (since it uses TextBoxFor).

OTHER TIPS

Not sure what you are trying to do and i dont want to make any assumptions but i have a feeling you may be going the wrong way. MVC as you probably Know has strongly typed views so that you can "bind" a view to a useful business object such as Person and then produce HTML by using something like

Html.TextBoxFor(p => p.Name)

where p is a Person

That thing you are trying to build seems to be a hack to achieve this. Cant you just create meaningful objects that hold your information and then pass them to strongly typed views? If another page has the same fields then pass the same object.

The answer here depends on whether or not you will know how many fields you have up front.

If you do, then you should create a strongly typed model to bind your mvc view to, and use data annotations as follows:

public class MyModel
{
    [Display(Name="Field name 1")
    public string Field1 { get; set; }

    [Display(Name="Field name 2")
    public string Field2 { get; set; }
}

Then in your view you can use the following code:

@Html.LabelFor(model => model.Field1)
@Html.TextBoxFor(model => model.Field1)

@Html.LabelFor(model => model.Field1)
@Html.TextBoxFor(model => model.Field1)

If however you don't know the number of fields up front and therefore can't populate a strongly typed model like this, then I would advise you do the following:

  • Add a navigation property to Field so you can get at the Value easily
  • Write some code to map between the database to perhaps a dictionary of
  • Write a loop in your view and use the old school html helpers like this:

...

@for (var key in model.FieldDictionary.Keys)
{
    @Html.Label("key", model.FieldDictionary(key))
    @Html.TextBox(model.FieldDictionary(key))
}

Please note this code is not tested, and in the second example you will have to figure out how to get the data back in when you post the form, but hopefully should give you a starting point.

Hope this helps!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top