Search code examples
asp.net-mvcdevexpresshtml-helper

HTML Extensions for wrapping other extensions


Most times when using DevEx MVC extensions, I find myself having to use repetitive code to generate the controls/layouts that I use on a regular basis. For example, I tend to prefer left-aligned captions to controls. Ideally, I'd be able to do something like this and have it "just work":

@Html.DevExpress().TextBoxFor(m => m.Notes).GetHtml()

However, in order to place the caption on the left, I need to also pass in a settings object for it, or dome something much more verbose such as:

@Html.DevExpress().TextBox(
    s => {
        // ...
        s.Properties.CaptionCellStyle.Width = 100;
        // ...
    }
).Bind(Model.Notes).GetHtml()

What I thought to do was create my own set of extensions that would wrap the DevEx extensions, giving me some sort of common/core customization layer, so I could do something like this:

@Html.MyComponents().TextBoxFor(m => m.Notes)

This call would in turn call the DevExpress TextBoxExtension with a common set of settings and output the DevEx textbox as desired.

I've worked this up via custom html extensions (code below), but have two issues with this basic implementation:

  1. The control renders at the very top of the Body element, not at the position in which it's placed in the view, and
  2. There's a JavaScript error "ASPxClientTextBox" is not defined (this is part of the client-side scripting that DevEx uses with their controls).

I was hoping this would be an easy "wrap it and go" type of scenario. Is there some basic concept of these custom HTML extensions that I'm missing? Or does anyone know if this is a general limitation in trying to wrap another company's pre-existing extensions?

Here's the code I have implemented (which is not yet fully fleshed out, just trying for proof of concept here):

public static class HtmlHelpers
{
    public static MyComponentsHtmlHelpers<TModel> MyComponents<TModel>(this HtmlHelper<TModel> html) {
        return new MyComponentsHtmlHelpers<TModel>(html);
    }
}


public class MyComponentsHtmlHelpers<TModel>
{

    private HtmlHelper<TModel> html; 

    public MyComponentsHtmlHelpers(HtmlHelper<TModel> html) {
        this.html = html;
    }

    public MvcHtmlString TextBoxFor<TValue>(Expression<Func<TModel, TValue>> expression) {

        var data = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
        string propertyName = data.PropertyName;

        System.Diagnostics.Debug.WriteLine("PROPERTY NAME: " + propertyName);

        TextBoxSettings s = new TextBoxSettings();
        s.Name = "textbox_" + propertyName;
        s.Properties.Caption = propertyName;
        s.Properties.CaptionCellStyle.Width = 100;

        TextBoxExtension tb = new TextBoxExtension(s);

        return tb.GetHtml();


    }

}

Solution

  • Nevermind - cleaning the solution and rebuilding as well as force refreshing the test browser a few times and ensure there's no cache and... now everything works as intended.

    (not sure if I ought to delete this question or leave it around in case someone wants to attempt the same... I'll leave it for now, feel free to remove)