1

我想扩展 ASP.NET MVC 的 TextBox,以便它有条件地切换其 CSS 值(基于模型中的数据)。但是,我不想将该逻辑放在我的视图中(通过有条件地更改 htmlAttributes/通过那里的方法调用),而是扩展类,这样我就不会弄乱我的视图。基本上我希望 TextBox 在创建时查看模型以查看它是否具有具有自己名称的字典条目,然后查找关联的 CSS 值(如果找到)。

我遇到的问题是:

1)我如何扩展它?TextBox 本身已经是一个扩展方法而不是一个类,所以我不能“继承”?

2) 我如何将影响 TextBox 属性的条件从我的控制器方法传达给 TextBox?

4

4 回答 4

4

可能您不应该将文本框耦合回模型。以一种方式拥有依赖关系总是更好的主意。从模型到视图。

所以间接的答案是有另一个将接受枚举或布尔值的扩展方法,并根据它添加或不添加类名。

<%= Html.StyledTextBox("myField", ViewData["ShouldBeStyled"]) %>

也有直接的答案。

要扩展 ASP.NET MVC,您应该编写自己的扩展方法。您可以随时调用下划线扩展方法。所以你的代码可能看起来像:

public static class MyCoolExtension
{
  public static string TextBox(this HtmlHelper htmlHelper, string name)
  {
     // get data from htmlHelper.ViewData and call another extension methods of the HtmlHelper 
    var className = htmlHelper.ViewData["someClass"];
    return htmlHelper.TextBox("myField", "30", new { @class = className });
  }
}
于 2009-08-18T07:30:57.433 回答
1

您可以做的一件事是使用 ViewData 将所需的 CSS 类传递给您的视图,然后视图不需要知道您的逻辑来执行此操作。

要回答您的具体问题,

1:你是对的,你不能扩展它,但这里有两种选择:一种是完全避免扩展它的需要,并利用提供的东西(例如使用 ViewData),另一种是实现你的自己的。如果您愿意,可以下载 MVC 源代码并直接从那里工作。

2:考虑一下你的控制器中的一些东西:

if (someCondition)
{
    ViewData["someClass"] = "foo";
}
else
{
    ViewData["someClass"] = "snazzle";
}

然后在你看来:

<%= Html.TextBox("myField", "30", new { @class = ViewData["someClass"] }) %>

祝你好运!
-F!

于 2009-08-18T07:26:51.543 回答
0

根据它对您的重要性,您还可以使用 jQuery 来应用格式。选择特定的文本框非常容易。

说“取决于它对您的重要性”,因为有一组用户禁用了 JavaScript(不能忽略),在这种情况下,格式将不会被应用。

于 2009-08-18T10:23:20.877 回答
0

这就是为什么我对 MVC 团队决定在任何地方都使用字符串感到如此不满的原因。向文本框添加类不应该是 TextBox HtmlHelper 关心的问题,它应该是构建 HTML 的一个单独方面。这是使用语义模型定义 Html 的更好解决方案。我将在这里使用 TagBuilder,但我强烈建议您查看 FubuMvc 中包含的 HtmlTags 库。

public TagBuilder TextBox(this HtmlHelper helper, string name, string value)
{
   var tag = new TagBuilder("input");
   tag.MergeAttribute("type", "text");
   tag.MergeAttribute("name", name);
   tag.MergeAttribute("value", value);
   return tag;
}

现在,由于我们返回了一个语义 (TagBuilder) 模型,我们可以继续修改模型,然后再将其转换为 HTML 文字。ConditionallyAddClass 是一个可重用的扩展方法,它将一个类应用于任何 TagBuilder 模型:

public TagBuilder ConditionallyAddClass<T>(this TagBuilder tag, string @class, T model, Func<T, bool> condition)
{
   if(condition(model))
   {
      tag.AddCssClass(@class);
   }
   return tag;
}

在您看来,您现在可以这样做(假设 StyleAgeTextbox 是一个布尔属性):

<%= Html.TextBox("Age", Model.Age).ConditionallyAddClass("customClass", Model, m => m.StyleAgeTextbox) %>

视图引擎会自动调用 TagBuilder 上的 ToString() 以获取正确的 HTML。

我希望这能给你基本的想法。当然有很多方法可以扩展它。您可以有一个标准的命名约定并使用一种dynamic类型来绕过使用表达式,或者您可以有查找表或强类型整个事物以使用成员表达式(例如 TextBoxFor(m => m.Age))。我更喜欢像 Fubu那样将整个东西移动到一个 html 约定框架中,但这可能超出了大多数项目的范围。

于 2010-07-20T20:02:02.373 回答