Несколько IEnumerable реализации в mvc3 на VIew
@{IEnumerable<BC.Models.APPLICATION> data = ViewBag.list;}
@Html.Grid(data).Columns(columns =>
{
columns.Add(c => c.APPLICATION_NO).Titled("Application No").Filterable(true);
})
Но я хочу сделать что-то подобное:
@if(some conditon)
{
@{IEnumerable<BC.Models.APPLICATION> data = ViewBag.list;}
}
else
{
@{IEnumerable<BC.Models.RIGHTS> data = ViewBag.list;}
}
@Html.Grid(data).Columns(columns =>
{
columns.Add(c => c.APPLICATION_NO).Titled("Application No");
})
Но это не работает, может кто-нибудь иметь представление об этом.
Теперь, если я делаю что-то подобное, это работает
@if(some conditon)
{
@{IEnumerable<BC.Models.APPLICATION> data = ViewBag.list;}
@Html.Grid(data).Columns(columns =>
{
columns.Add(c => c.APPLICATION_NO).Titled("Application No");
})
}
else
{
@{IEnumerable<BC.Models.RIGHTS> data = ViewBag.list;}
@Html.Grid(data).Columns(columns =>
{
columns.Add(c => c.APPLICATION_NO).Titled("Application No");
})
}
Моя проблема в том, что свойство APPLICATION_NO присутствует в обоих классах Model, поэтому я не хочу использовать
@Html.Grid(data).Columns(columns =>
{
columns.Add(c => c.APPLICATION_NO).Titled("Application No");
})
Дважды в моем коде.
3 ответа
Ваша проблема в том, что вы не используете, когда наиболее важные понятия в MVC: просмотр моделей.
Что касается вашего последнего комментария, то, что вы хотите использовать, - это модель представления, то есть класс, созданный специально для отправки данных в представление для его отображения.
Для этого:
- создать публичный класс, который имеет
APPLICATION_NO
(необходимо для класса модели представления) - создайте другой открытый класс, который будет вашей моделью представления. Это класс, который формирует данные по мере необходимости в шаблоне бритвы (в этом случае он будет содержать список класса, определенного в 1)
- в вашем контроллере верните представление, передающее модель в качестве второго параметра. Т.е. не используйте
ViewBag
/ViewData
, но модель представления вместо этого, как этоreturn View("ViewName", model)
- используйте модель в своем представлении: объявите тип модели, используя
@model
и использовать его внутри шаблонов Razor с предоставленнымиModel
переменная
Таким образом, вы формируете данные на сервере и избегаете включения большого количества кода в шаблон Razor (что не рекомендуется). И, конечно, у вас есть intellisense, и ваши шаблоны становятся напечатанными.
Код для 1:
public class ApplicationModel
{
public int APPLICATION_NO {get; set;}
}
Код для 2:
public class ApplicationsViewModel
{
public List<ApplicationModel> Applications { get; set; }
}
Код на 3 (внутри контроллера)
var model = new ApplicationsViewModel();
if (...) // include the condition to choose the kind of data inside the list
{
model.Applications = list.Select(item =>
new ApplicationModel { APPLICATION_NO = item.APPLICATION_NO } ).ToList()
}
else
{
// same code here, for the other kind of data in the list
}
// return the view with this model
return View("ApplicationView", model);
Код для 4:
// decalre the model type at the beginning
@model YourNamespace.ApplicationViewModel;
// access the model using the Model variable
@Html.Grid(Model.Applications).Columns(columns =>
{
columns.Add(c => c.APPLICATION_NO).Titled("Application No");
})
Это позволяет создавать приложения MVC с несколькими преимуществами, такими как тестируемость, повторное использование кода, читаемость или доступность ModelState
, Поверьте мне, многие из этих вещей действительно, очень важны, особенно ModelState
,
Кроме того, вы можете использовать аннотации кода (атрибуты, которые предоставляют дополнительную информацию помощникам HTML) в вашей модели представления, эти атрибуты могут обеспечивать метки, проверку и некоторые другие автоматические функции.
Не сомневайтесь, чтобы включить все необходимые свойства в вашу модель представления.
Использование модели представления позволяет вам создать специальный класс без необходимости изменять свой домен или классы бизнес-уровня, то есть вам не нужно использовать интерфейсы, аннотации кода и так далее. Однако часто интересно добавлять аннотации кода в бизнес-классы и вкладывать их в модели представлений.
Помните, что иногда вы можете использовать ту же модель представления для отправки данных обратно на сервер, указав их в качестве типа параметра вашего действия POST.
Кстати, интерфейсное решение хорошее, но это решение не требует интерфейса. (Это решение будет иметь лучшую реализацию с использованием этого интерфейса, но это ваш выбор).
@if(some conditon)
{
@{IEnumerable<BC.Models.APPLICATION> data = ViewBag.list;}
}
else
{
@{IEnumerable<BC.Models.RIGHTS> data = ViewBag.list;}
}
@Html.Grid(data).Columns(columns =>
{
columns.Add(c => c.APPLICATION_NO).Titled("Application No");
})
Код не может работать, потому что данные объявляются в блоки if. Если сетка должна работать только с общими полями двух классов, вы можете подумать об использовании интерфейса, который APPLICATION и RIGHTS реализуют и изменяют код следующим образом:
@{IEnumerable<BC.Models.IAPPLICATION_NO> data = (IEnumerable<BC.Models.IAPPLICATION_NO>)ViewBag.list;}
@Html.Grid(data).Columns(columns =>
{
columns.Add(c => c.APPLICATION_NO).Titled("Application No");
})
где IAPPLICATION_NO - это интерфейс типа:
public interface IAPPLICATION_NO
{
string APPLICATION_NO { get; }
}
Я не знаю, что такое APPLICATION_NO, поэтому я использовал строку, и интерфейс может определить только get для grid.
В противном случае, если вам нужно отобразить разные данные для этих двух типов, вам следует рассмотреть возможность использования двух представлений или другого объявления сетки в блоках if.
Я работал над образцом моего ответа на VS:
Я прилагаю вам код:
public interface AInterface
{
string AProperty { get; }
}
public class AList : AInterface
{
public string AProperty { get; set; }
}
public class BList : AInterface
{
public string AProperty { get; set; }
}
это классы
Теперь контроллер:
public class TestController : Controller
{
public ActionResult Index()
{
var random = new Random((int)DateTime.Now.Ticks);
if (random.Next() % 2 == 0)
ViewBag.List = new List<AList> { new AList { AProperty = "Atestvalue" } };
else
ViewBag.List = new List<BList> { new BList { AProperty = "Atestvalue" } };
return View();
}
}
и вид:
@{
ViewBag.Title = "Index";
IEnumerable<TestMvcApplication.Interfaces.AInterface> test = ViewBag.List;
}
<h2>Index</h2>
@foreach (var item in test)
{
<div>
@item.AProperty
</div>
}
это решает вашу проблему, как вы можете видеть
Без использования интерфейсов:
@{IEnumerable<dynamic> data = (IEnumerable<dynamic>)ViewBag.list;}
@Html.Grid(data).Columns(columns =>
{
columns.Add(c => c.APPLICATION_NO).Titled("Application No");
})
но вы теряете завершение IntelliSense, и если член отсутствует, я думаю, что вы получите ошибку во время выполнения.
Я попробовал вашу сборку Grid, но она использует выражение C# и несовместима с динамическим. Другим решением может быть приведение одного списка к другому с помощью LINQ в контроллере:
IEnumerable<BC.Models.Application> data;
if (some condition)
{
data = applicationList; //applicationList's type is IEnumerable<BC.Models.Application>
}
else
{
data = rightsList.Select(t => new Application { APPLICATION_NO = t.APPLICATION_NO }); //rightsList's type is IEnumerable<BC.Models.RIGHTS>
}
ViewBag.list = data;
В представлении вы можете сохранить рабочий код, который вы разместили в верхней части вопроса. У вас нет многотипной поддержки IEnumerable, потому что вы используете только один тип, но без использования общего интерфейса между этими классами, я думаю, что мы должны перейти к размышлению, но я думаю, что этот код сложно написать.
Почему бы и нет
@{string columnName = "default column name";
if(some_condition)
{
// I'm not sure what's going on with the data variable
columnName = "alternate column name";
}
else
{
// Again, do your stuff with the data variable
}
}
@Html.Grid(data).Columns(columns =>
{
columns.Add(c => c.APPLICATION_NO).Titled(columnName);
})
Я думаю, что вы в конечном итоге получите (в лучшем случае) запутанный код, если попытаетесь быть слишком умными в своих взглядах. Сетка для рендеринга IEnumerable<A>
не подходит для рендеринга IEnumerable<B>
если A:ISomeInterface
а также B:ISomeInterface
и сетка оказывает ISomeInterface
, В качестве альтернативы просто передайте имя столбца как свойство модели представления.