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

Per*_*Per 5 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; }
Run Code Online (Sandbox Code Playgroud)

根据我的值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; }
Run Code Online (Sandbox Code Playgroud)

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

Row*_*man 5

以下是如何进行此操作的示例。

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

一个人有两个属性

  • 姓名
  • 活跃

IsActive属性是一个布尔值,将用于确定用户名的显示形式。

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

[DisplayIf("IsActive", "This value is true.", "This value is false.")]
Run Code Online (Sandbox Code Playgroud)

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

模型/人物.cs

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

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

属性/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;
    }
}
Run Code Online (Sandbox Code Playgroud)

让我们创建一个简单的控制器和操作。我们将使用通用的/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);
    }

}
Run Code Online (Sandbox Code Playgroud)

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

ViewModels/HomeViewModels.cs

public class HomeIndexViewModel
{
    public IEnumerable<Person> Persons { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

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

视图/Home/Index.cshtml

@model HomeIndexViewModel

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<div>
    @Html.DisplayForModel()
</div>
Run Code Online (Sandbox Code Playgroud)

DisplayForModel当您创建此显示模板时将起作用:

视图/Home/DisplayTemplates/HomeIndexViewModel.cshtml

@model HomeIndexViewModel

@Html.DisplayFor(m => m.Persons)
Run Code Online (Sandbox Code Playgroud)

DisplayFor-> 当您创建此显示模板时,人员将起作用:

视图/共享/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>
    }
}
Run Code Online (Sandbox Code Playgroud)

但是这个显示模板中的这些方法是什么?创建一个名为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;
    }
}
Run Code Online (Sandbox Code Playgroud)

扩展/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);
    }
}
Run Code Online (Sandbox Code Playgroud)

最终输出:

输出