使用 HTML Helper 通过键绑定到字典的 MVC 模型
MVC Model Binding to Dictionary by Key with HTML Helper
在 MVC(4) 中过滤数据列表时,我将多个过滤器输入绑定到 ViewModel 模型中的字典。
我已经能够通过这样的输入文字声明(.aspx 引擎)来做到这一点:
<input type="text" name='Model.Filters[matchId].Filter'
value='<%: Model.Filters["matchId"].Filter %>' />
其中 "matchId" 是要过滤的列的名称。 Model.Filter 字典定义为
IDictionary<string,FilterObject>
FilterObject 目前只是:
[Serializable]
public class FilterObject
{
public FilterObject()
{
Filter = "";
}
public FilterObject(String value)
{
Filter = value;
}
//[DefaultValue("")]
public String Filter { get; set; }
}
所以 - 只要 Model.Filters 字典使用过滤器输入的所有键进行初始化,它就可以工作,否则我们自然会得到一个 "key not found" 运行时异常。
将列名字符串硬编码到控制器中是丑陋的,感觉应该可以使用 @Html.TextBoxFor<>(....) 来避免异常,但我找不到有效的语法(或不只是中断无效的索引对象类型等)例如:
Html.TextBoxFor(m=>m.Filters.FirstOrDefault(k=>k.Key=="matchId").Value.Filter)
生产 HTML 个
<input id="Value_Filter" name="Value.Filter" type="text" value="" />
这显然没有任何用处
我很确定我只是遗漏了一些东西,但我发现的所有字典绑定示例都依赖于循环并绑定到一个 int 索引,我在这一点上很困惑,没有写一个自定义的助手似乎有点矫枉过正。
非常感谢任何帮助:-)
哈!我停止了与潮流的斗争,并为此写了一个Helper,比我想象的要容易:
public static MvcHtmlString TextBoxForFilterDictionary(this HtmlHelper helper, IDictionary<string, FilterObject> filters, string fieldName, object htmlAttributes = null)
{
FilterObject filter;
if (!filters.TryGetValue(fieldName, out filter))
{
filter = new FilterObject();
}
string nameAttribute = String.Format("Model.Filters[{0}].Filter", fieldName);
MvcHtmlString html = helper.TextBox(nameAttribute, filter.Filter, htmlAttributes);
return html;
}
并且在 HTML:
<%: Html.TextBoxForFilterDictionary(Model.Filters, "matchId")%>
<!-- a bunch of other formatting HTML -->
<%: Html.TextBoxForFilterDictionary(Model.Filters, "matchName")%>
<!-- and so on -->
我的通用 ViewModel 现在包含列表排序、分页和过滤所需的一切,不需要过滤器字典初始化,也看不到弱类型对象。
值得付出额外的努力!
在 MVC(4) 中过滤数据列表时,我将多个过滤器输入绑定到 ViewModel 模型中的字典。
我已经能够通过这样的输入文字声明(.aspx 引擎)来做到这一点:
<input type="text" name='Model.Filters[matchId].Filter'
value='<%: Model.Filters["matchId"].Filter %>' />
其中 "matchId" 是要过滤的列的名称。 Model.Filter 字典定义为
IDictionary<string,FilterObject>
FilterObject 目前只是:
[Serializable]
public class FilterObject
{
public FilterObject()
{
Filter = "";
}
public FilterObject(String value)
{
Filter = value;
}
//[DefaultValue("")]
public String Filter { get; set; }
}
所以 - 只要 Model.Filters 字典使用过滤器输入的所有键进行初始化,它就可以工作,否则我们自然会得到一个 "key not found" 运行时异常。
将列名字符串硬编码到控制器中是丑陋的,感觉应该可以使用 @Html.TextBoxFor<>(....) 来避免异常,但我找不到有效的语法(或不只是中断无效的索引对象类型等)例如:
Html.TextBoxFor(m=>m.Filters.FirstOrDefault(k=>k.Key=="matchId").Value.Filter)
生产 HTML 个
<input id="Value_Filter" name="Value.Filter" type="text" value="" />
这显然没有任何用处
我很确定我只是遗漏了一些东西,但我发现的所有字典绑定示例都依赖于循环并绑定到一个 int 索引,我在这一点上很困惑,没有写一个自定义的助手似乎有点矫枉过正。
非常感谢任何帮助:-)
哈!我停止了与潮流的斗争,并为此写了一个Helper,比我想象的要容易:
public static MvcHtmlString TextBoxForFilterDictionary(this HtmlHelper helper, IDictionary<string, FilterObject> filters, string fieldName, object htmlAttributes = null)
{
FilterObject filter;
if (!filters.TryGetValue(fieldName, out filter))
{
filter = new FilterObject();
}
string nameAttribute = String.Format("Model.Filters[{0}].Filter", fieldName);
MvcHtmlString html = helper.TextBox(nameAttribute, filter.Filter, htmlAttributes);
return html;
}
并且在 HTML:
<%: Html.TextBoxForFilterDictionary(Model.Filters, "matchId")%>
<!-- a bunch of other formatting HTML -->
<%: Html.TextBoxForFilterDictionary(Model.Filters, "matchName")%>
<!-- and so on -->
我的通用 ViewModel 现在包含列表排序、分页和过滤所需的一切,不需要过滤器字典初始化,也看不到弱类型对象。
值得付出额外的努力!