Шаблоны редактора во время выполнения

Эту проблему немного сложно объяснить, поэтому я попытаюсь привести пример. Скажем, у меня есть следующий тип:

public class FieldResult<T> {
    public Field Field { get; set; }
    public T Answer { get; set; }

    public FieldResult(Field field) {
        Field = field;
    }
}

Теперь скажем, у меня есть следующая модель представления:

public class Form {
    public IList<FieldResult<object>> Results { get; set; }

    public Form(IList<Field> fields) {
        Results = fields.Select(f => new FieldResult<object>(f)).ToList();
    }
}

Если я скажу следующее в представлении:

@foreach (var result in Model.Results) {
    @Html.EditorFor(m => result, "CheckBoxField")
}

Теперь предположим, что у меня есть следующий шаблон редактора CheckBoxField:

@model FieldResult<bool>
@Html.CheckBoxFor(m => m.Answer)

Все компилируется нормально, но во время выполнения я получаю следующую ошибку:

Элемент модели, переданный в словарь, имеет тип «FieldResult1[System.Object]', but this dictionary requires a model item of type 'FieldResult1[System.Boolean]».

Я был бы признателен, если бы кто-нибудь мог сказать, возможно ли это, и, возможно, предложить способ сделать это. Спасибо


person nfplee    schedule 25.11.2013    source источник


Ответы (1)


Вы пытаетесь передать значение FieldResult<object> в шаблоне, модель которого имеет тип FieldResult<bool>, они разных типов, поэтому вы получаете эту ошибку. Вы можете либо изменить свое свойство Results и сделать его IList<FieldResult<bool>>, либо отобразить элементы коллекции в своем представлении.

Если вам нужно создать различные типы результатов, вы также можете рассмотреть возможность использования наследования классов:

public abstract class FieldResult {
    public Field Field { get; set; }

    public FieldResult(Field field) {
        Field = field;
    }
}

public class BooleanFieldResult : FieldResult {
    public bool Answer { get; set; }

    public FieldResult(Field field) : base(field) {
    }
}

Ваш класс Form будет выглядеть так:

public class Form {
    public IList<FieldResult> Results { get; set; }

    public Form(IList<Field> fields) {
        Results = // ... you choose which child class inherited from FieldResult you want to use
    }
}

Ваш взгляд проверит, какой это тип:

@foreach (var result in Model.Results) {
    if(result is BooleanFieldResult) {
        var booleanResult = (BooleanFieldResult)result;
        @Html.EditorFor(m => booleanResult , "CheckBoxField")
    }
}

Тогда ваш шаблон CheckBoxField будет выглядеть так:

@model BooleanFieldResult
@Html.CheckBoxFor(m => m.Answer)
person Réda Mattar    schedule 25.11.2013
comment
Благодаря этому возникла ошибка. Шаблоны можно использовать только с доступом к полям, доступом к свойствам, индексом одномерного массива или выражениями пользовательского индексатора с одним параметром. поэтому я взял слепок вне редактора и сохранил его в переменной, и он отобразился правильно. Я пока оставлю это открытым, так как мне нужно немного поработать, но спасибо, что направили меня в правильном направлении. - person nfplee; 25.11.2013
comment
Я только что закончил свое тестирование, и это работает хорошо. Я смог избавиться от большого количества ненужного кода, который у меня был, и этот подход позволяет мне выполнять пользовательскую проверку для каждого из типов полей. Спасибо еще раз. - person nfplee; 25.11.2013