我遇到以下情况-我需要编写一个自定义的附加元数据属性,该属性基于另一个属性值(来自同一模型),将一个值添加到AdditionalValues字典中。现在,我的问题是我无法访问属性类中的模型实例。
[AttributeUsage(AttributeTargets.Property)]
public class ExtendedAdditionalMetadataAttribute : Attribute, IMetadataAware
{
#region Private properties
private string extraFieldToCheck { get; set; }
private string extraFieldValueToCheck { get; set; }
private string fieldToBeAdded { get; set; }
private string fieldValueToBeAdded { get; set; }
#endregion
#region Constructor
public ExtendedAdditionalMetadataAttribute(string extraFieldToCheck, string extraFieldValueToCheck,
string fieldToBeAdded, string fieldValueToBeAdded)
{
this.extraFieldToCheck = extraFieldToCheck;
this.extraFieldValueToCheck = extraFieldValueToCheck;
this.fieldToBeAdded = fieldToBeAdded;
this.fieldValueToBeAdded = fieldValueToBeAdded;
}
#endregion
public void OnMetadataCreated(ModelMetadata metadata)
{
// HOW TO GET THE MODEL CLASS INSTANCE???
// metadata.ContainerType is correct by metadata.Container is null.
}
}
从代码注释中可以看到,在OnMetadataCreated内部,我需要访问Model类实例,但是,尽管ContainerType是正确的,但Container属性为NULL。
您能帮我提示一下这个问题吗?
先感谢您!
你家
后期编辑
考虑到我没有给出太多解释,我还将在此处粘贴一个示例,说明如何在模型类上使用此属性:
/// <summary>
/// Gets or sets the IsAccountCreated
/// </summary>
/// <value>The IsAccountCreated.</value>
[UIHint("FormFieldStringTemplate")]
[ExtendedAdditionalMetadata("IsExternalAccount", "true", "ReadOnly", "true")]
public override Boolean IsAccountCreated { get; set; }
/// <summary>
/// Gets or sets the IsAccountEnabled
/// </summary>
/// <value>The IsAccountEnabled.</value>
[Display(Name = "Este cont activ?")]
[UIHint("FormFieldStringTemplate")]
[ExtendedAdditionalMetadata("IsExternalAccount", "true", "ReadOnly", "true")]
public override Boolean IsAccountEnabled { get; set; }
/// <summary>
/// Gets or sets the IsExternalAccount
/// </summary>
/// <value>The IsExternalAccount.</value>
[Display(Name = "Este cont extern?")]
[UIHint("FormFieldStringTemplate")]
[AdditionalMetadata("ReadOnly", "true")]
public override Boolean IsExternalAccount { get; set; }
以后再编辑
尽管@ stephen-muecke给出的响应在当前情况下更为简单并且可以接受,但是出于编程挑战的考虑,我一直在寻找其他选择,并且发现了以下可能性:实现自定义DataAnnotationsModelMetadataProvider
类。简单来说-它可以工作,并且只有在模型类是简单类的情况下,我才能获得模型类实例,但是有很多缺点-例如,如果您有一个Model类并且在视图中使用它那就可以了,但是如果您在另一个类(视图模型中的模型)中有一个类,则此方法不再可用。
再次感谢您@ stephen-muecke!
由于您似乎需要访问模型的多个属性,因此属性应以class
(AttributeTargets.Class
)为目标并应用于模型,而不是属性。这可能意味着您需要添加另一个属性,该属性是您尝试将此属性应用到的属性的名称。注意metadata.ContainerType
仅提供给您type
,而不提供此实例,因此您只能获取其属性的默认值。
编辑
如果需要将属性应用于模型中的多个属性,则无法访问容器,OnMetadataCreated
因为元数据是从最内层的属性中创建的,因此尚未创建模型的元数据。
根据OP的评论,更好的解决方案是创建自定义html帮助器。例如,根据另一个属性的值生成一个只读的文本框
namespace MyHelpers.Html
{
public static class ReadOnlyHelpers
{
public static MvcHtmlString ReadOnlyTextBoxIf<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression, bool isReadOnly)
{
object attributes = isReadOnly ? new { @readonly = "readonly" } : null;
return InputExtensions.TextBoxFor(helper, expression, attributes);
}
}
}
并在您看来用作
@Html.ReadOnlyTextBoxIf(m => m.SomeTextProperty, Model.SomeBooleanValue)
创建“只读”复选框要困难一些,因为该readonly
属性对无效checkbox
。为了防止用户交互,您需要将其禁用,但这意味着该值不会回发
public static MvcHtmlString ReadOnlyCheckBoxIf<TModel>(this HtmlHelper<TModel> helper, Expression<Func<TModel, bool>> expression, bool isReadOnly)
{
if (isReadOnly)
{
// If you want to 'visually' render a checkbox (otherwise just render a div with "YES" or "NO")
ModelMetadata metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
StringBuilder html = new StringBuilder();
// Add a hidden input for postback
html.Append(InputExtensions.HiddenFor(helper, expression).ToString());
// Add a visual checkbox without name so it does not post back
TagBuilder checkbox = new TagBuilder("input");
checkbox.MergeAttribute("type", "checkbox");
checkbox.MergeAttribute("disabled", "disabled");
if ((bool)metaData.Model)
{
checkbox.MergeAttribute("checked", "checked");
}
html.Append(checkbox.ToString());
return MvcHtmlString.Create(html.ToString());
}
else
{
// return normal checkbox
return InputExtensions.CheckBoxFor(helper, expression);
}
}
并在您看来用作
@Html.ReadOnlyCheckBoxIf(m => m.IsAccountCreated, Model.IsExternalAccount)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句