Wanted to add the htmlAttributes overload to Chad's answer above for anyone looking to drop it in and have it work. All the other helpers can be built from these examples pretty easily. (Thanks Chad, your extension helped ease my transition into using knockout!)
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;
}
}
}