是否可以创建条件属性作为DisplayIf?

时间:2013-11-27 23:25:35

标签: c# asp.net-mvc-4

我想创建一个与我的viewmodel一起使用的属性。我想根据第三个值显示不同的文本字符串。

我想做这样的事......

[DisplayIf("IsPropertyValid", true, Name="value 1")]
[DisplayIf("IsPropertyValid", false, Name="value 2")]
public string MyProperty { get; set; }

public bool IsPropertyValid { get; set; }

根据我的值IsPropertyValid是否为真,我想显示一个或另一个。 IE浏览器。当属性IspPropertyValid等于true时,“value 1”将是displaytext,如果不是,则为“value 2”。

这是否可以使用ASPNET.MVC属性?或者甚至更好......像......一样的组合....

[DisplayIf("IsPropertyValid", new {"value 1", "value 2"})].
public string MyProperty { get; set; }

public bool IsPropertyValid { get; set; }

然后该属性检查IsPropertyValid的值,并确保显示的值为“value 1”或“value 2”。

1 个答案:

答案 0 :(得分:4)

这是一个如何解决这个问题的例子。

我们要做的是创建一个名为 Person 的简单类,并显示一些关于它们的基本信息。

一个人有两个属性

  • 名称
  • IsActive

IsActive属性是bool值,将是用于确定用户名称显示为的属性。

最终我们要做的是将一个名为DisplayIf的新属性应用于Name属性。它看起来像这样:

[DisplayIf("IsActive", "This value is true.", "This value is false.")]

首先,让我们创建我们的模型。创建一个名为 Person 的类,并将其放入 Models 文件夹中。

模型/ Person.cs

public class Person
{
    [DisplayIf("IsActive", "This value is true.", "This value is false.")]
    public string Name { get; set; }
    public bool IsActive { get; set; }
}

创建一个名为属性的文件夹,然后将以下类放入其中:

属性/ DisplayIfAttribute.cs

public class DisplayIfAttribute : Attribute
{
    private string _propertyName;
    private string _trueValue;
    private string _falseValue;

    public string PropertyName
    {
        get { return _propertyName; }
    }

    public string TrueValue
    {
        get { return _trueValue; }
    }

    public string FalseValue
    {
        get { return _falseValue; }
    }

    public DisplayIfAttribute(string propertyName, string trueValue, string falseValue)
    {
        _propertyName = propertyName;
        _trueValue = trueValue;
        _falseValue = falseValue;
    }
}

让我们创建一个简单的控制器和动作。我们将使用常见的 / Home / Index

控制器/ HomeController.cs

public class HomeController : Controller
{
    public ActionResult Index()
    {
        HomeIndexViewModel viewModel = new HomeIndexViewModel();

        Person male = new Person() { Name = "Bob Smith", IsActive = true };
        Person female = new Person() { Name = "Generic Jane", IsActive = false };

        Person[] persons = {male, female};

        viewModel.Persons = persons;

        return View(viewModel);
    }

}

创建一个名为 ViewModels 的新文件夹,并创建一个 HomeViewModels.cs 类。

的ViewModels / HomeViewModels.cs

public class HomeIndexViewModel
{
    public IEnumerable<Person> Persons { get; set; }
}

我们的索引视图非常简单。

查看/主页/ Index.cshtml

@model HomeIndexViewModel

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<div>
    @Html.DisplayForModel()
</div>
创建此显示模板时,

DisplayForModel将起作用:

查看/主页/ DisplayTemplates / HomeIndexViewModel.cshtml

@model HomeIndexViewModel

@Html.DisplayFor(m => m.Persons)

DisplayFor - &gt;创建此显示模板时,人员将工作:

查看/共享/ DisplayTemplates / Person.cshtml

@model Person

@foreach (var prop in ViewData.ModelMetadata.Properties)
{
    if (prop.HasDisplayIfAttribute())
    { 
        <p>@Html.DisplayIfFor(x => prop)</p>
    }
    else
    { 
        <p>@Html.DisplayFor(x => prop.Model)</p>
    }
}

但是这个显示模板中的这些方法是什么?创建一个名为 Extensions 的新文件夹,并添加以下类:

扩展/ ModelMetaDataExtensions.cs

public static class ModelMetaDataExtensions
{
    public static bool HasDisplayIfAttribute(this ModelMetadata data)
    {
        var containerType = data.ContainerType;
        var containerProperties = containerType.GetProperties();
        var thisProperty = containerProperties.SingleOrDefault(x => x.Name == data.PropertyName);
        var propertyAttributes = thisProperty.GetCustomAttributes(false);
        var displayIfAttribute = propertyAttributes.FirstOrDefault(x => x is DisplayIfAttribute);

        return displayIfAttribute != null;
    }
}

扩展/ HtmlHelperExtensions.cs

public static class HtmlHelperExtensions
{
    public static IHtmlString DisplayIfFor<TModel, TProperty>
        (this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
        where TProperty : ModelMetadata
    {
        string returnValue = string.Empty;

        var modelMetaData = expression.Compile().Invoke(helper.ViewData.Model);

        var containerType = typeof(TModel);
        var containerProperties = containerType.GetProperties();
        var propertyInfo = containerProperties
            .SingleOrDefault(x => x.Name == modelMetaData.PropertyName);
        var attribute = propertyInfo.GetCustomAttributes(false)
            .SingleOrDefault(x => x is DisplayIfAttribute) as DisplayIfAttribute;
        var conditionalTarget = attribute.PropertyName;

        var conditionalTargetValue = (bool)containerType
            .GetProperty(conditionalTarget).GetValue(helper.ViewData.Model);

        if (conditionalTargetValue)
        {
            returnValue = attribute.TrueValue;
        }
        else
        {
            returnValue = attribute.FalseValue;
        }

        return MvcHtmlString.Create(returnValue);
    }
}

最终输出:

Output