#c# #asp.net-mvc
#c# #asp.net-mvc
Вопрос:
Я создал класс для хранения некоторых статических данных:
static public class ReferenceData
{
[DisplayName("Status")]
public IEnumerable<SelectListItem> StatusType
{
get
{
return new[]
{
new SelectListItem { Value = "0", Text = "Release" },
new SelectListItem { Value = "1", Text = "Beta" },
new SelectListItem { Value = "2", Text = "Alpha" },
};
}
}
}
Теперь я хотел бы использовать данные этого класса для заполнения выпадающего списка в представлении. У меня есть следующая модель представления:
public class adminViewModel
{
public HouseData HouseData { get; set; }
public string Status { get; set; }
public ReferenceData ReferenceData { get; } // <<<<<< My problem here
}
@Html.DropDownListFor(
x => x.Status,
new SelectList(Model.ReferenceData.StatusType, "Value", "Text"),
new { style = "display: inline;" }
)
Проблема для меня в том, что я не уверен, является ли это допустимым способом сделать это, потому что я использую статический класс, и когда у меня есть get; там внутри {}, он жалуется во время компиляции сообщением об ошибке, в котором говорится:
static types cannot be used as return types
Действительно ли мне нужно сделать его нестатическим и создать экземпляр класса, прежде чем я смогу использовать его в viewmodel, даже если данные всегда статичны?
Ответ №1:
Это недопустимый C #. Вместо этого вы могли бы использовать статический метод:
public static class ReferenceData
{
public static IEnumerable<SelectListItem> GetStatusType()
{
return new[]
{
new SelectListItem { Value = "0", Text = "Release" },
new SelectListItem { Value = "1", Text = "Beta" },
new SelectListItem { Value = "2", Text = "Alpha" },
};
}
}
и затем :
public class AdminViewModel
{
public string Status { get; set; }
[DisplayName("Status")]
public IEnumerable<SelectListItem> Statuses
{
get
{
return ReferenceData.GetStatusType();
}
}
}
наконец, в представлении:
@Html.DropDownListFor(
x => x.Status,
new SelectList(Model.Statuses, "Value", "Text"),
new { style = "display: inline;" }
)
Комментарии:
1. за исключением того, что данные такого типа должны находиться в viewbag, или viewdata, или tempdata. куда угодно, кроме viewmodel. эти данные не имеют никакого отношения к модели.
2. @nathan gonzalez, ViewBag и ViewData являются самыми злыми вещами в ASP.NET В MVC для меня такого рода данных определенно не должно быть. Временные данные, я не знаю => есть несколько редких случаев, когда это может быть полезно. Я думаю, вы имеете в виду, что эти данные могут быть жестко запрограммированы в методе репозитория, который запрашивает действие контроллера для заполнения модели. Тогда я бы согласился с вами.
3. жесткий код в репозитории? я не думаю, что я когда-либо сделал бы это. почему вы ненавидите viewbag и viewdata. этот тип данных — это то, для чего они предназначены. viewmodel предназначена для модели views, частью которой эти данные явно не являются.
4. @nathan gonzalez, да, у меня была бы реализация моего интерфейса репозитория, которую я бы, например, вызвал
AdminOptionsMemory
, потому что, например, у меня нет базы данных, и я не хочу хранить эти значения в файлах, я просто хочу, чтобы они были в памяти. Что касается ViewBag / ViewData, то они вносят слабую типизацию в представления, если вы используете их, это означает, что вы не используете строго типизированные представления и модели представлений, если вы используете их, вы не получаете Intellisense, если вы используете их, вам нужно выполнять приведения в ваших представлениях, чтобы вызвать надлежащую перегрузку метода, … и я могу продолжить с этим5. я не говорю, что вы не должны использовать строго типизированное представление, я полностью за использование viewmodel для данных представления, связанных с моделью. и я получаю слабо типизированную проблему, но для данных, которых нет в модели views, viewdata — это место, куда их можно поместить. я полагаю, согласен с несогласием.
Ответ №2:
Вы уверены, что хотите, чтобы ваш класс был статическим, а не свойство? Если у вас есть статическое свойство, вам не нужно создавать экземпляр, чтобы получить доступ к свойству. Дополнительная информация: Статические классы и члены статического класса (руководство по программированию на C #):
Комментарии:
1. Я хотел сделать класс статическим, чтобы мне не пришлось создавать его экземпляр. Это правильное утверждение? Я удалил статику из класса и добавил статику к типу состояния. Затем в модели представления я получаю другое сообщение: …..ReferenceData.get’ должен объявить тело, потому что оно не помечено как abstract или extern. Автоматически реализуемые свойства должны определять как методы доступа get, так и set.
2. сделайте свойство статическим вместо класса
3. @DavidH если вы хотите, чтобы ReferenceData были автоматически реализованным свойством, доступным только для чтения, тогда вам следует написать public ReferenceData ReferenceData { get; private set; }
Ответ №3:
Вы хотите сделать это:
public class ReferenceData
{
private static readonly SelectListItem[] Items = new[]
{
new SelectListItem { Value = "0", Text = "Release" },
new SelectListItem { Value = "1", Text = "Beta" },
new SelectListItem { Value = "2", Text = "Alpha" },
};
[DisplayName("Status")]
public IEnumerable<SelectListItem> StatusType
{
get { return Items; }
}
}
(сделайте элементы статическими при использовании экземпляра класса).
Вы также можете использовать синглтон:
public class ReferenceData
{
private static readonly ReferenceData _instance = new ReferenceData();
private ReferenceData()
{
}
public ReferenceData Instance { get { return _instance; } }
[DisplayName("Status")]
public IEnumerable<SelectListItem> StatusType
{
get
{
return new[]
{
new SelectListItem { Value = "0", Text = "Release" },
new SelectListItem { Value = "1", Text = "Beta" },
new SelectListItem { Value = "2", Text = "Alpha" },
};
}
}
}
И использовать это в вашей модели:
public class adminViewModel
{
public HouseData HouseData { get; set; }
public string Status { get; set; }
public ReferenceData ReferenceData { get {return ReferenceData.Instance; } }
}
Комментарии:
1. Ваш ответ работает очень хорошо. Только один вопрос. Как я могу получить доступ к StatusType в программе C #. Я попытался выполнить var data1 = new ReferenceData(); но он выдает сообщение об ошибке: Ссылочные данные недоступны из-за их уровня защиты.
2.
var data = ReferenceData.Instance.StatusType
Ответ №4:
Прежде всего создайте свою модель следующим образом..
public class ReferenceData
{
public string SelectRuleId { get; set; }
public IEnumerable<SelectListItem> StatusType
{
get
{
return new[]
{
new SelectListItem { Value = "0", Text = "Release" },
new SelectListItem { Value = "1", Text = "Beta" },
new SelectListItem { Value = "2", Text = "Alpha" },
};
}
}
}
Затем создайте новое действие в любом контроллере, подобном этому..
public ActionResult About()
{
var model = new ReferenceData();
ViewBag.Message = "DropDown Selected For ";
return View(model);
}
Затем используйте этот HTML-код в своем представлении действий…
@model MVCDropDownList.Models.AnswersViewModel
@using (Html.BeginForm())
{ @Html.DropDownListFor(x => x.SelectRuleId , new SelectList(Model.StatusType, "Value", "Text"), new { id = "DId" })
}