问题描述
我已经搜索过问题,发现可能,但我仍然需要一些帮助。
I have already searched for the question and found possible answer, but I still need some help.
我想写一个html-helper来扩展已经存在的LabelFor方法
I am trying to write an html-helper to extend functionality of already existing LabelFor method
public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, IDictionary<string, object> htmlAttributes)
{
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
string htmlFieldName = ExpressionHelper.GetExpressionText(expression);
//string labelText = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();
var labelText = html.LabelFor(expression);
if (String.IsNullOrEmpty(labelText.ToString()))
{
return MvcHtmlString.Empty;
}
if (metadata.IsRequired)
{
labelText = new MvcHtmlString(labelText.ToString().Substring(0, labelText.ToString().Length - 8).Trim() +
"<span style=\"color:red\" class=\"required-marker\">*</span></label>");
}
TagBuilder tag = new TagBuilder("label");
tag.MergeAttributes(htmlAttributes);
tag.Attributes.Add("for", html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(htmlFieldName));
tag.SetInnerText(labelText.ToString());
return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal));
}
我试图添加一个功能,其中Method将检查变量是否有required标志,然后执行某些操作(在这种情况下在标签结尾添加红色)
I am trying to add a functionality, where Method would check if variable has a "required" flag, and then performs something (adds red * at the end of label in that case)
[Required]
[Display(Name = "Year")]
public string ProjectYr { get; set; }
但是,我觉得我要覆盖整个LabelFor功能。有没有办法简单地添加新的功能到现有的LabelFor方法,同时保留原始的所有功能,而不覆盖它? 覆写无法运作,因为我的方法是静态的。
However, I feel like I am overwriting the entire LabelFor functionality. Is there a way to simply add new functionality to existing LabelFor method while preserving all functions of the original without overriding it? Override doesn't work anyway since my method is static.
非常感谢您! p>
Thank you very much in advance!
推荐答案
这是一个完整的例子,你做的是什么
Here's a complete example that does what your asking
public static class LabelExtensions
{
public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression, IDictionary<String, Object> htmlAttributes,
String requiredMarker = "*")
{
return LabelHelper(html, ModelMetadata.FromLambdaExpression(expression, html.ViewData),
ExpressionHelper.GetExpressionText(expression), null, htmlAttributes, requiredMarker);
}
public static MvcHtmlString LabelFor<TModel, TValue>(this HtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression, Object htmlAttributes, String requiredMarker)
{
return LabelFor(html, expression, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes), requiredMarker);
}
internal static MvcHtmlString LabelHelper(HtmlHelper html, ModelMetadata metadata, String htmlFieldName,
String labelText = null, IDictionary<String, Object> htmlAttributes = null, String requiredMarker = null)
{
var resolvedLabelText = labelText ??
metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();
var tag = new TagBuilder("label");
tag.Attributes.Add("for",
TagBuilder.CreateSanitizedId(html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(htmlFieldName)));
tag.SetInnerText(resolvedLabelText);
tag.MergeAttributes(htmlAttributes, true);
if (metadata.IsRequired && !String.IsNullOrWhiteSpace(requiredMarker))
{
var requiredSpan = new TagBuilder("span") {InnerHtml = requiredMarker};
requiredSpan.AddCssClass("required");
tag.InnerHtml += requiredSpan;
}
var result = tag.ToString(TagRenderMode.Normal);
return new MvcHtmlString(result);
}
}
这里是单元测试
public static class LabelExtensionFixtures
{
[TestFixture]
public class should_return_label_with_required_info : MvcExtensionFixtureBase
{
private class TestClass
{
[Required]
public Guid Id { get; set; }
}
private MvcHtmlString _expectedResult;
private HtmlHelper<TestClass> _sut;
private MvcHtmlString _result;
[SetUp]
public void Given()
{
//arrange
_expectedResult =
MvcHtmlString.Create(
"<label class=\"control-label col-md-2\" for=\"Id\">Id<span class=\"required\">*</span></label>");
_sut = CreateHtmlHelper(new TestClass {Id = Guid.NewGuid()});
//act
_result = _sut.LabelFor(model => model.Id, new { @class = "control-label col-md-2" }, "*");
}
[Test]
public void Test()
{
//asert
Assert.That(_result.ToHtmlString(), Is.EqualTo(_expectedResult.ToHtmlString()));
}
}
}
public abstract class MvcExtensionFixtureBase
{
protected HtmlHelper<T> CreateHtmlHelper<T>(T instance)
{
var viewDataDictionary = new ViewDataDictionary<T>(instance);
var viewContext = A.Fake<ViewContext>();
A.CallTo(() => viewContext.ViewData).Returns(viewDataDictionary);
var viewDataContainer = A.Fake<IViewDataContainer>();
A.CallTo(() => viewDataContainer.ViewData).Returns(viewDataDictionary);
return new HtmlHelper<T>(viewContext, viewDataContainer);
}
}
这篇关于C#html-helper扩展现有方法而不覆盖?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!