开发者

Creating custom UI elements en MVC 3

开发者 https://www.devze.com 2023-03-11 08:27 出处:网络
In my project I have the requirement where certain fields depending of a certain condition should be editable or just readonly.

In my project I have the requirement where certain fields depending of a certain condition should be editable or just readonly.

So I though that doi开发者_开发知识库ng this for every field was an overkill

@if (Model.CanEdit)
{ 
    @Html.TextBoxFor(model => Model.Foo, new { width = "100px" })
}
else
{ 
    @Html.TextBox(model => Model.Foo, new { width = "100px", @readonly = "readonly"})
}

I decided to use an editor template, but then I realised that the width cannot be fixed, so I was wondering what's the best way to send parameters to an Editor template? Also it should handle the scenario that width may not be defined and not use the width property at all. I found that ViewData may help with this, but having a code that looks like this makes me feel I'm doing something wrong.

@inherits System.Web.Mvc.WebViewPage<string>
@if (Model.CanEdit)
{ 
    @if(ViewData["width"] == null)
    {
        @Html.TextBox("", Model, new { width = ViewData["width"].ToString() })
    }
    else
    {
        @Html.TextBox("", Model)
    }
}
else
{ 
    @if(ViewData["width"] == null)
    {
        @Html.TextBox("", Model, new { width = ViewData["width"].ToString() , @readonly = "readonly"})
    }
    else
    {
        @Html.TextBox("", Model, new {@readonly = "readonly"})
    }
}

I wonder if there could be a way to create a helper so I could make something like:

@MyTextBoxFor(model => Model.Foo, true) @* true would be or readonly *@
@MyTextBoxFor(model => Model.Foo, true, 100) @* 100 would be the width length *@


kapsi's answer is great, but if you want to use your helper in a strongly typed view, here's the basic syntax. It's a little sloppy, but you can add overloads as you see fit.

public static class MyHelpers
{
    public static MvcHtmlString MyTextBoxFor<TModel, TProperty>(
        this HtmlHelper<TModel> htmlHelper, 
        Expression<Func<TModel, TProperty>> expression, 
        bool flagReadonly,
        int? widthProperty) where TModel : class
    {
        MemberExpression memberExpression = expression.Body as MemberExpression;
        string parameterName = memberExpression.Member.Name;

        return new MvcHtmlString(
            string.Format("<input id=\"{0}\" name=\"{0}\" {1} {2} />",
            parameterName, // name and if of parameter
            flagReadonly ? "readonly=\"readonly\"" : string.Empty,
            widthProperty.HasValue ? 
                string.Format("width=\"{0}px\"", (int)widthProperty) : 
                string.Empty));
    }
}

Of course, this way, you're afforded the ability to strongly type your view elements

@Html.MyTextBoxFor(model => model.Foo, true)

and

@Html.MyTextBoxFor(model => model.Foo, true, 100)

etc


A simple example:

public static class MyHelpers
{
    public static MvcHtmlString MyTextBox(this HtmlHelper htmlHelper, string name, string value = "", bool canEdit = false, int width = 100)
    {
        if (canEdit)
        {
            return htmlHelper.TextBox(name, value, new { width = width.ToString() + "px" });
        }
        else
        {
            return htmlHelper.TextBox(name, value, new { @readonly = "readonly", width = width.ToString() + "px" });
        }
    }
}

Then register the Class in web.config or use a using statement

@using test.Helpers
@Html.MyTextBox("test")
@Html.MyTextBox("test", "asdf")
@Html.MyTextBox("test", "asdf", true, 500)

Result:

<input id="test" name="test" readonly="readonly" value="" type="text" width="100px">
<input id="test" name="test" readonly="readonly" value="asdf" type="text" width="100px">
<input id="test" name="test" value="asdf" type="text" width="500px">
0

精彩评论

暂无评论...
验证码 换一张
取 消