2013-01-17 22 views
1

我使用ASP.NET MVC3和Razor。如何讓ASP.NET MVC 3呈現Html.CheckBoxFor和相應的隱藏元素與反向值?

我在我的模型中有一個布爾值,我想在我的視圖中顯示爲複選框。不過,我希望複選框指示布爾狀態的反向。換句話說,選擇複選框應該在提交表單時將綁定模型對象設置爲false,而不是true。反之亦然。

我能做到這一點,設置渲染的複選框,輸入元素的值屬性:

@Html.CheckBoxFor(model => model.MyBoolean, new { value = "false" }) 

但自動創建隱藏的輸入元素仍然有假值。因此,它們都具有false值,這意味着綁定模型對象始終設置爲false。

那麼如何強制HTML助手將隱藏元素設置爲true,並將複選框元素設置爲false?我知道(a)我可以改變模型和數據庫,(b)我可以在提交之前用javascript改變值,(c)我可以在提交後交換控制器中接收到的任何值。我可能會做其中的一個,但我並沒有要求可能的解決方案;我在問是否可以讓HTML助手按我的意願去做。我已經進行了大量搜索,並且沒有在官方或非官方來源的任何地方看到這一點。看起來他們應該有一個「交換」選項或其他東西。

+0

隱藏字段我增加了一個可能的解決方案,請參閱我的編輯: –

+0

「@ Html.CheckBox(」YourElementName「,Model.MyBoolean)」 是你想要的嗎? –

+0

@Leon_SFS:不,您的代碼將呈現相同。我希望能夠在我的問題中使用確切的代碼,但幫助者知道我將該值設置爲false,因此將相應的隱藏輸入元素的值設置爲true。隱藏元素的目的是表示複選框元素的值的對立面,所以助手應該確保它始終是相反的。 – dairystatedesigns

回答

2
class ViewModel { 
     public bool MyBoolean {get;set;} 
     public bool DisplayValue { 
      get { 
       return ! MyBoolean ; 
      } 

      set { 
       MyBoolean = !value; 
      } 
     } 
    } 

並綁定到DisplayValue,因爲它的setter更新你MyBoolean財產反正。

編輯:

再次閱讀您的問題後:

您可以使用HtmlHelper來做到這一點 - 但不使用複選框,您可以使用下拉菜單。下拉菜單將定義「oppisite」值和文本。

myModelInstance.PossibleValues = new[] { new SelectListItem { Value = "false", Text = "Not false" }, new SelectListItem { Value = "true", Text = "Not true" } }; 

請注意,描述與您希望模型的含義相反。因此,例如。真正的你可能有文本爲「隱藏」和假你可能有文字爲「可見」,真正爲「已禁用」,假的「已啓用」等你查看

然後:

@Html.DropDownList(Model.MyBoolean.ToString(), Model.PossibleValues) 

在查看或更新之前,模型將更新爲正確的值,而不必執行布爾切換。

+0

這是最好的答案_if_不可能讓HTML助手做我想做的事情而不改變視圖模型。 – dairystatedesigns

+1

這正是ViewModel的用途,確保您的視圖具有正確/已轉換的數據,以便爲用戶正確顯示數據。就像ViewModel將Guid轉換爲用戶可以選擇的字符串值列表一樣。 –

+0

編輯中的另一個很好的選擇,但不幸的是設計需要在我的特殊情況下使用複選框。在我看來,一個真正的MVC架構將通過視圖渲染嚴格實現這一點。我明白@ErikPhilips的觀點,即ViewModel通常用於此目的,而ViewModel與DB模型不同,但我想我不同意這個框架的設計方式。就好像HTML助手是處理設計/可用性考慮的更合乎邏輯的地方。無論如何,我會接受這個答案是正確的。 – dairystatedesigns

0

對於未來的讀者,我個人認爲,HtmlHelpers的設計是爲了呈現Html(顧名思義)。我喜歡創建不同的方式來渲染項目是創建EditFor和DisplayFor模板。爲了確保這是高度可重用的,我還創建了專門爲這些模板設計的模型。通過您的設計,我的模型和模板可能如下所示:

/Models/Controller/ControllerActionViewModel。CS

public class ControllerActionViewModel 
{ 
    public ControllerActionViewModel() 
    { 
    this.CheckboxBoolTemplate = new CheckboxBoolTemplate(false, true); 
    } 

    [Display(Name = "My Boolean")] 
    public SelectBoolTemplate MyBoolean { get; set; } 
} 

/TemplateModels/ControllerActionViewModel.cs

public sealed class SelectBoolTemplate 
{ 
    private bool _valuesSwapped = false; 
    private bool? _value; 
    private bool _defaultValue = false; 

    public SelectBoolTemplate() 
    { 
    } 

    public SelectBoolTemplate(bool valuesSwapped) 
    { 
    this._valuesSwapped = valuesSwapped) 
    } 

    public SelectBoolTemplate(bool defaultValue, bool valuesSwapped) 
    { 
    this._defaultValue = defaultValue; 
    this._valuesSwapped = valuesSwapped) 
    } 

    public bool Value 
    { 
    get 
    { 
     if (this._value.HasValue) 
     { 
     return this._value.Value 
     } 
     return this._defaultValue; 
    } 
    set 
    { 
     this._value = value; 
    } 
    } 
} 

/Views/Shared/EditorTemplates/SelectBoolTemplate.cshtml

@model SelectBoolTemplate 

@{ 
string propertyName = ViewContext.ViewData.ModelMetadata.PropertyName; 
string fullPropertyName = ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix; 
string labelText = ViewContext.ViewData.ModelMetadata.DisplayName 
        ?? ViewContext.ViewData.ModelMetadata.PropertyName; 
} 

@Html.LabelForModel() 
@Html.Checkbox(fullPropertyName, Model.Value) 
+0

好的解決方案。我也考慮過這個選擇,但似乎這樣的矯枉過正幾乎不存在。此外,我認爲它應該是'新的SelectBoolTemplate(false,true);'在ViewModel代碼中。 – dairystatedesigns

0

我知道這是爲時已晚原始的查詢,但對於任何人在未來閱讀有一個替代Ë方式來處理與反轉僞/真爲選中/取消其無需更改模型複選框 - 創建虛假的複選框,並真正

<input id="@Html.IdFor(model => model.BoolProperty)" name="@Html.NameFor(model => model.BoolProperty)" type="checkbox" value="false" @(Model.BoolProperty? "" : "checked=\"checked\"") /> 
<input name="@Html.NameFor(model => model.BoolProperty)" type="hidden" value="true" />