2009-08-18 63 views
1

我想擴展ASP.NET MVC的TextBox,以便有條件地切換其CSS值(基於模型中的數據)。但是,我不希望在我的視圖中放置該邏輯(通過有條件地更改htmlAttributes /通過方法調用),而是擴展該類,以免混亂我的視圖。基本上,我希望創建時的TextBox能夠查看Model,看看它是否有一個帶有自己名字的字典條目,然後查找關聯的CSS值(如果它找到它)。ASP.NET MVC:'擴展'Html.TextBox有條件地具有CSS值?

我遇到的問題有:

1)如何擴展它? TextBox本身已經是一個擴展方法,而不是一個類,所以我不能「繼承」?

2)如何將影響TextBox屬性的條件從我的控制器方法傳遞到TextBox?

回答

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 }); 
    } 
} 
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!

+0

我已經知道了第2號,並希望避免這一點(正如我在我的問題中寫的)。我可能會嘗試直接查看/使用MVC源代碼,除非其他人有指示如何執行此操作。 – Alex 2009-08-18 07:33:09

0

根據您對自己的重要程度,還可以使用jQuery應用格式設置。選擇特定的文本框非常容易。

是說「取決於它對你有多重要」,因爲有一組用戶禁用了JavaScript(這是不能忽略的),在這種情況下,格式不會被應用。

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 does這樣的html約定框架中,但這可能超出了大多數項目。