带复选框和单选按钮的MVC3分层视图模型

时间:2012-02-09 09:24:32

标签: asp.net-mvc-3 hierarchical editorfor radiobuttonfor checkboxfor

我正在拉扯我遗漏的小头发 - 过去几个月一直在学习MVC,所以我相对较新,尽管我已经涵盖了很多基础...... / p>

我在尝试使用相对复杂的视图模型输出复选框和单选按钮时遇到了问题。

我有以下视图(删除了不相关的字段):

@model CreateMediumModel
@using(Html.BeginForm()) {
                <div class="formField">
                    <div class="label">
                        @Html.LabelFor(m => m.MetaData)
                    </div>
                    <div class="input">
                        @Html.EditorFor(m => m.MetaData)
                    </div>
                    @Html.ValidationMessageFor(m => m.MetaData)
                </div>

}

分层视图模型如下所示:

public class CreateMediumModel {
    public List<MetaData> MetaData { get; set; }
}

public class MetaData {
    /// <summary>
    /// The media type that this meta data belongs to.
    /// </summary>
    public int MediaTypeID { get; set; }

    /// <summary>
    /// The unique ID for the meta data.
    /// </summary>
    public int MetaDataID { get; set; }

    /// <summary>
    /// The unique text-based identifier for the meta data. Unique per MediaType.
    /// </summary>
    public string Key { get; set; }

    /// <summary>
    /// The UI description of the meta data.
    /// </summary>
    public string Description { get; set; }

    /// <summary>
    /// The max length of text based data.
    /// </summary>
    public int Length { get; set; }

    /// <summary>
    /// Provides a pre-defined list of values for the meta data.
    /// </summary>
    public List<MetaDataOption> Options { get; set; }

    /// <summary>
    /// Provides the text-based value for the meta data.
    /// </summary>
    public string Value { get; set; }

    /// <summary>
    /// Determines which value/s to use from the object graph
    /// </summary>
    public MetaDataDataType Type { get; set; }

    /// <summary>
    /// Defines the UI sort order of the meta data
    /// </summary>
    public int SortOrder { get; set; }
}

public class MetaDataDataType {
    public int MetaDataTypeID { get; set; }
    public MetaDataDataTypeEnum Type { get; set; }
    public bool TextBased { get; set; }
}

public class MetaDataOption {
    /// <summary>
    /// The unique ID for the option
    /// </summary>
    public int MetaDataOptionID { get; set; }

    /// <summary>
    /// The pre-defined option value to display.
    /// </summary>
    public string Value { get; set; }

    /// <summary>
    /// The sort order of the value in the list.
    /// </summary>
    public int SortOrder { get; set; }
}

public enum MetaDataEnum {
    Developer,
    PEGI,
    PEGIContent
}

public enum MetaDataDataTypeEnum {
    /// <summary>
    /// Simple text
    /// </summary>
    TEXT = 1,

    /// <summary>
    /// Multi-line text.
    /// </summary>
    MULTITEXT = 2,

    /// <summary>
    /// Simple number
    /// </summary>
    NUMBER = 3,

    /// <summary>
    /// Simple date
    /// </summary>
    DATE = 4,

    /// <summary>
    /// Simple time
    /// </summary>
    TIME = 5,

    /// <summary>
    /// Simple DateTime
    /// </summary>
    DATETIME = 6,

    /// <summary>
    /// Single option selection
    /// </summary>
    SELECTION = 7,

    /// <summary>
    /// Multi option selection
    /// </summary>
    MULTISELECTION = 8
}

每个元数据都有一个类型;该类型定义了如何编辑元数据以及如何显示元数据(以及数据存储在数据层中的位置)。事物的显示方面工作得很好。

当类型为“SELECTION”时,我想显示一组单选按钮,其中只能选择一个。当类型为“MULTISELECTION”时,我想显示一组复选框,其中可以选择多个复选框。我可以这样做,但我已经能够成功地将所选值绑定到模型。

目前,我正在使用编辑器模板来显示List,如下所示:

@model MetaData
@using Business.Enumerations

@if(Model != null) {
    @Html.HiddenFor(m => m.MetaDataID)
    <div class="metaData@(Model.MediaTypeID) checkbox">
        <div class="metaDescription">
            @Model.Description
        </div>
        <div class="metaValue">
            @switch(Model.Type.Type) {
                case MetaDataDataTypeEnum.NUMBER:
                case MetaDataDataTypeEnum.DATE:
                case MetaDataDataTypeEnum.TEXT:
                case MetaDataDataTypeEnum.TIME:
                case MetaDataDataTypeEnum.DATETIME:
                    @Html.TextBoxFor(m => m.Value)
                    break;
                case MetaDataDataTypeEnum.MULTITEXT:
                    @Html.TextAreaFor(m => m.Value)
                    break;
                case MetaDataDataTypeEnum.SELECTION:
                    foreach(var o in Model.Options) {
                        @Html.RadioButtonFor(m => m.Value, o.MetaDataOptionID) @o.Value
                    }
                    break;
                case MetaDataDataTypeEnum.MULTISELECTION:
                    foreach(var o in Model.Options) {
                        @Html.CheckBoxFor(m => m.Options.FirstOrDefault(opt => opt.Selected).Selected) @o.Value
                    }
                    break;
   }
        </div>
    </div>
}

当我克服这个问题时,这将被扩展,但是现在,它按预期输出所有内容 - 我看到SELECTION类型的单选按钮列表和MULTISELECTION类型的复选框列表,但它没有正确绑定到模型时我称之为提交行动。

我有点疯狂。任何人都可以看到任何明显的我做错了吗?

暂且不说:

我也尝试为MetaDataOption类创建一个编辑器模板,但是当指定模板名称时,似乎存在将List传递到子编辑器模板的错误(Html.EditorFor(m =&gt; ; m.Options,“MetaDataOptionsSingle”)和Html.EditorFor(m =&gt; m.Options,“MetaDataOptionsMulti”)) - 如果我没有为编辑器模板指定名称,模板可以有一个MetaDataOption模型,但是如果指定名称,则需要列表。


更新

好的,我已经设法让这个工作,但我现在遇到了对复选框进行不显眼验证的问题。修复方法如下:

MetaData编辑器模板现在看起来像这样:

@model MetaData
@using Business.Enumerations

@if(Model != null) {
    @Html.HiddenFor(m => m.Description)
    @Html.HiddenFor(m => m.Type)
    <div class="metaData@(Model.MediaTypeID) checkbox">
        <div class="metaDescription">
            @Model.Description
        </div>
        <div class="metaValue">
            @switch (Model.Type) {
                case MetaDataDataTypeEnum.NUMBER:
                case MetaDataDataTypeEnum.DATE:
                case MetaDataDataTypeEnum.TEXT:
                case MetaDataDataTypeEnum.TIME:
                case MetaDataDataTypeEnum.DATETIME:
                    @Html.TextBoxFor(m => m.Value)
                    break;
                case MetaDataDataTypeEnum.MULTITEXT:
                    @Html.TextAreaFor(m => m.Value)
                    break;
                case MetaDataDataTypeEnum.SELECTION:
                    if(Model.Options != null) {
                        foreach (var o in Model.Options) {
                            @Html.RadioButtonFor(m => Model.SelectedMetaDataOptionID, o.MetaDataOptionID)
                            @o.Value
                        }
                    }
                    break;
                case MetaDataDataTypeEnum.MULTISELECTION:
                    @Html.EditorFor(m => m.Options)
                    break;
            }
        </div>
    </div>
}

我为MULTISELECTION EditorFor添加了另一个EditorTemplate:

@model MetaDataOption

@if(Model != null) {
    @Html.HiddenFor(m => m.MetaDataOptionID)
    @Html.CheckBoxFor(m => m.Selected)
    @Model.Value
}

MetaDataOption类如下:

public class MetaDataOption {
    /// <summary>
    /// The unique ID for the option
    /// </summary>
    public int MetaDataOptionID { get; set; }

    /// <summary>
    /// The pre-defined option value to display.
    /// </summary>
    public string Value { get; set; }

    /// <summary>
    /// The sort order of the value in the list.
    /// </summary>
    public int SortOrder { get; set; }
}

模型现在在提交时正确填充。但是,验证发生在编辑器模板呈现的所有复选框上(在post操作方法中,因为我还没有实现客户端验证),但是在MetaDataOption类的“Selected”成员上没有数据注释。

需要注意的事项 - 如果没有选中复选框,则MetaData类的“Options”成员为null。

我试图将Selected属性设置为可以为空的bool(bool?),但是我在MetaDataOption编辑器模板中运行了CheckBoxFor()辅助函数而不接受可以为空的bool。

这让我发疯了......我花了两天时间试图让一些工作用ASP.Net进行调整!

0 个答案:

没有答案