我认为拥有 EditorFor HTML 助手的扩展版本会非常有用,它会自动为 Knockout JS 写出值数据绑定。
这适用于客户端视图模型和服务器端视图模型相同的情况——我已经通过使用 ko 映射并通过 AJAX 获取视图模型来自动生成客户端视图模型。
有没有其他人尝试过这样的事情,或者是否有任何项目包含类似于我在这里的想法?
这样做的好处是,在重构时不会有丢失数据绑定值的危险。
我认为拥有 EditorFor HTML 助手的扩展版本会非常有用,它会自动为 Knockout JS 写出值数据绑定。
这适用于客户端视图模型和服务器端视图模型相同的情况——我已经通过使用 ko 映射并通过 AJAX 获取视图模型来自动生成客户端视图模型。
有没有其他人尝试过这样的事情,或者是否有任何项目包含类似于我在这里的想法?
这样做的好处是,在重构时不会有丢失数据绑定值的危险。
我们已经按照这些思路做了一些事情,它远非完美,我们在自定义扩展中还有更多,但我提取了本质。
using System.Web.Mvc.Html;
namespace System.Web.Mvc
{
public static class EditorForExtensions
{
public static MvcHtmlString TextBoxForViewModel<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
{
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
var htmlAttributes = HtmlAttributesForKnockout(metadata);
return htmlHelper.TextBoxFor(expression, htmlAttributes);
}
private static Dictionary<string, object> HtmlAttributesForKnockout(ModelMetadata metadata)
{
var htmlAttributes = new Dictionary<string, object>();
var knockoutParameter = String.Format("value: {0}", metadata.PropertyName);
htmlAttributes.Add("data-bind", knockoutParameter);
return htmlAttributes;
}
}
}
然后可以像这样使用它:
@Html.TextBoxForViewModel(m => m.Name)
想要将 htmlAttributes 重载添加到上面乍得的答案中,以供任何希望将其放入并使其正常工作的人。所有其他助手都可以很容易地从这些示例中构建出来。(感谢乍得,您的扩展帮助我轻松过渡到使用淘汰赛!)
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Web.Mvc.Html;
namespace System.Web.Mvc {
public static class KnockoutExtensions {
public static MvcHtmlString KnockoutTextBoxFor<TModel, TProperty>( this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression ) {
var metadata = ModelMetadata.FromLambdaExpression( expression, htmlHelper.ViewData );
var htmlAttributes = HtmlAttributesForKnockout( metadata );
return htmlHelper.TextBoxFor( expression, htmlAttributes );
}
public static MvcHtmlString KnockoutTextBoxFor<TModel, TProperty>( this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object attributes ) {
// convert passed anonymous object (attributes) into IDictionary<string,object> to pass into attribute parser
var attrs = HtmlHelper.AnonymousObjectToHtmlAttributes( attributes ) as IDictionary<string, object>;
var metadata = ModelMetadata.FromLambdaExpression( expression, htmlHelper.ViewData );
var htmlAttributes = HtmlAttributesForKnockout( metadata, attrs );
return htmlHelper.TextBoxFor( expression, htmlAttributes );
}
private static Dictionary<string, object> HtmlAttributesForKnockout( ModelMetadata metadata, IEnumerable<KeyValuePair<string, object>> attributes = null ) {
var htmlAttributes = new Dictionary<string, object>();
var knockoutParameter = String.Format( "value: {0}", metadata.PropertyName );
htmlAttributes.Add( "data-bind", knockoutParameter );
if ( attributes != null ) foreach ( var attr in attributes ) htmlAttributes.Add( attr.Key, attr.Value );
return htmlAttributes;
}
}
}