【问题标题】:MVC use Html.CheckBoxFor with nullable BoolMVC 使用 Html.CheckBoxFor 和可为空的 Bool
【发布时间】:2016-11-08 14:55:55
【问题描述】:

我有一个复选框,我想在我的视图中显示一个与名为 public 的字段相关的复选框,它基本上说明了特定行是否是公共的。在数据库中,这是一个位字段,但它允许空值,因为该表以前是如何工作的。

我正在使用 Html.CheckBoxFor 但它抱怨这个字段,因为在系统中它不是 bool 类型,而是 bool?类型。我想要做的是,如果字段值为 null,那么它在前端被视为 false(不幸的是,更新数据库值本身不是一种选择)。

我尝试使用 GetValueOrDefault,并在我的模型文件中按照以下方式放置一个默认值:

public class Model
{
    public bool? Public { get; set; }

    public SearchModel()
    { 
        Public = false;
    }
}

但是它抱怨这个,给我以下错误:

An exception of type 'System.InvalidOperationException' occurred in System.Web.Mvc.dll but was not handled in user code

Additional information: Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.

所以我不确定我该如何从这里取得进展,有人可以帮我指出正确的方向吗?

编辑:

这是我试图用来显示复选框的视图上的代码。在这种情况下,我添加了一些额外的 html 属性,以便它显示为切换而不是简单的复选框:

Html.CheckBoxFor(model => model.Public, new {data_toggle = "toggle", data_off = "No", data_on = "Yes", data_size = "small"})

【问题讨论】:

  • 我不得不质疑为什么有人会调用变量Public,在不相关的注释上,您的模型称为Model,但它的构造函数称为SearchModel,这样就可以了造成一些问题
  • 听起来您正在将模型绑定到 EF 实体。这是非常不灵活的,通常不是一个好主意。
  • @AlfieGoodacre 好点,我一直在改变一些东西,一定错过了。至于变量,这就是在数据库中调用该字段的内容,因此我在模型文件中保持变量名称相同。不幸的是,我对数据库字段的名称没有任何发言权
  • 要使您的代码正常工作,您需要实例化模型并将其传递给视图,例如模型模型 = 新模型();返回视图(模型);也许一些控制器操作代码将有助于识别问题。

标签: c# asp.net-mvc


【解决方案1】:

当您将表达式传递给无法评估的模板化助手之一时,您会遇到特定异常。请记住,当您使用基于表达式的帮助器时,您实际上不是按值传递属性,而是一个表达式,表示模型上的一个属性,帮助器将使用它来引用该属性,从中生成字段名称等。

你没有显示你正在执行的实际代码,但这意味着你不能做这样的事情:

@Html.EditorFor(m => m.Public.GetValueOrDefault())

因为模板化帮助程序无法将其解析为与模型上的属性匹配的表达式。

至于您在这里的实际基本问题,即如果值为 null,则将值设置为 false,您只需要自定义 getter 和 setter。 @utaco 的答案提供了新的更简单的 C# 6.0 自动实现属性的默认方法:

public bool? Public { get; set; } = false;

对于以前版本的 C#,您需要以下内容:

private bool? public;
public bool? Public
{
    get { return public ?? false; }
    set { public = value; }
}

但是,当您无意将 Public 保留为可空布尔值时,它实际上是空值只会使您的代码更加困难。假设您可以将其更改为 bool(即,这是一个视图模型,而不是绑定到您的数据库表的实际实体类),那么您应该这样做。不过,您仍然希望将私有保留为可为空的。这允许您在 setter 中接受 null,但在 getter 中将它们强制转换为 false 值,这意味着 public 的实际值将始终为 truefalse,即不为 ​​null。

【讨论】:

  • 非常感谢您的帮助。我从来没有真正想过使用视图模型来解决这个问题,但我已经创建了一个并将其插入,现在它似乎正在工作
【解决方案2】:

如果你使用 c# 6.0 或更高版本,你可以使用这个:

public bool YourProp { get; set; } = false; 

【讨论】:

  • 当我这样做时,我得到与主帖中相同的错误
【解决方案3】:

这不需要初始化。 @Html.EditorFor(m => m.AnyNullableProperty) 下面按预期对我有用。

        <div class="form-group">
            @Html.LabelFor(model => model.RequiresBatchNumberOnReceipt, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(m => m.RequiresBatchNumberOnReceipt)

                @Html.ValidationMessageFor(model => model.RequiresBatchNumberOnReceipt)
            </div>
        </div>

【讨论】:

    【解决方案4】:

    我采纳了 Chris Pratt 的想法,但使用方式不同。我创建了一个 ViewModel 并添加了一个不可为空的属性来更新可空属性,反之亦然。

    public bool? Public { get; set; }
    
    private bool _public;
    public bool _Public
    {
        get { return Public ?? false; }
        set 
        { 
          _public = value; 
          Public = value; 
        }
    }
    

    现在在视图中,您将使用不可空值而不是可空值进行更新

    Html.CheckBoxFor(model => model._Uploaded)
    

    这种方法的唯一问题是,如果保存更改,您将不会返回 null。这对我有用,因为 NULL 值在我们的程序中代表 false。

    【讨论】:

    • 当我按照这里的解释创建一个假属性时它才起作用,然后在之前填写它以保存记录,当我必须在页面上显示这个属性时,我需要填写假属性与原始财产。我找不到其他方法。
    猜你喜欢
    • 2014-11-29
    • 2012-09-22
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多