Click here to Skip to main content
15,912,578 members

Welcome to the Lounge

   

For discussing anything related to a software developer's life but is not for programming questions. Got a programming question?

The Lounge is rated Safe For Work. If you're about to post something inappropriate for a shared office environment, then don't post it. No ads, no abuse, and no programming questions. Trolling, (political, climate, religious or whatever) will result in your account being removed.

 
GeneralRe: Wine Glasses Are Seven Times Larger Today Than They Were 300 Years Ago Pin
CPallini14-Dec-17 21:26
mveCPallini14-Dec-17 21:26 
GeneralRe: Wine Glasses Are Seven Times Larger Today Than They Were 300 Years Ago Pin
den2k8814-Dec-17 21:56
professionalden2k8814-Dec-17 21:56 
GeneralRe: Wine Glasses Are Seven Times Larger Today Than They Were 300 Years Ago Pin
CPallini14-Dec-17 21:59
mveCPallini14-Dec-17 21:59 
GeneralRe: Wine Glasses Are Seven Times Larger Today Than They Were 300 Years Ago Pin
dandy7214-Dec-17 11:05
dandy7214-Dec-17 11:05 
GeneralRe: Wine Glasses Are Seven Times Larger Today Than They Were 300 Years Ago Pin
den2k8814-Dec-17 21:05
professionalden2k8814-Dec-17 21:05 
GeneralRe: Wine Glasses Are Seven Times Larger Today Than They Were 300 Years Ago Pin
Munchies_Matt14-Dec-17 21:43
Munchies_Matt14-Dec-17 21:43 
GeneralRe: Wine Glasses Are Seven Times Larger Today Than They Were 300 Years Ago Pin
PeejayAdams14-Dec-17 23:18
PeejayAdams14-Dec-17 23:18 
GeneralOverengineering 101 Pin
#realJSOP14-Dec-17 6:30
professional#realJSOP14-Dec-17 6:30 
Pay attention, class. THIS is how you go full-retard with your code.

I took this:
HTML
<div class="form-group">
    @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
        @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
    </div>
</div>

Down to this:
HTML
@Html.EditForEx(model => model.Name)

With this:
C#
public static partial class ExtendHtmlHelper2
{
    public static MvcHtmlString EditForEx<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
    {
        return html.EditForEx(expression, (ValidatorProperties)null, (LabelProperties)null, new EditorProperties());
    }

    public static MvcHtmlString EditForEx<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, CtrlProperties ctrlProperties)
    {
        ctrlProperties = (ctrlProperties == null) ? new CtrlProperties() : ctrlProperties
        return html.EditForEx(expression, ctrlProperties.Validator, ctrlProperties.Label, ctrlProperties.Editor);
    }

    private static MvcHtmlString EditForEx<TModel, TValue>(this HtmlHelper<TModel> html, 
                                                            Expression<Func<TModel, TValue>> expression, 
                                                            ValidatorProperties validatorProperties, 
                                                            LabelProperties labelProperties, 
                                                            EditorProperties editorProperties)
    {
        MvcHtmlString validator = html.BuildValidator(expression, validatorProperties);
        MvcHtmlString label = html.BuildLabel(expression, labelProperties);
        MvcHtmlString editor    = null;
        if (editorProperties == null)
        {
            editorProperties = new EditorProperties();
        }
        object attributes = editorProperties.BuildAttributes();
        editor = html.EditorFor(expression, attributes);
        return WrapOuter(label, WrapInner(editor, validator, ControlType.TextBox));
    }

    private static MvcHtmlString WrapOuter(MvcHtmlString label, MvcHtmlString innerWrap)
    {
        StringBuilder html = new StringBuilder();
        html.AppendLine("<div class=\"form-group\">").AppendLine(label.ToString()).AppendLine(innerWrap.ToString()).AppendLine("</div>");
        return new MvcHtmlString(html.ToString());
    }

    private static MvcHtmlString WrapInner(MvcHtmlString field, MvcHtmlString validation, ControlType ctrlType)
    {
        StringBuilder html = new StringBuilder();
        string ctrlDiv = "<div class=\"col-md-10\"";
        switch (ctrlType)
        {
            case ControlType.CheckBox     : ctrlDiv = WrapInnerCheck(field, validation, "USE WrapInnerCheck").ToString(); break;
            case ControlType.DropList     :
            case ControlType.FileUpload   :
            case ControlType.TextArea     :
            case ControlType.TextBox      : ctrlDiv = string.Concat(ctrlDiv,">"); break;
            case ControlType.TextOnly     : ctrlDiv = string.Concat(ctrlDiv," style=\"width:280px;\">"); break;
            case ControlType.ActionLink   : 
            case ControlType.ActionButton : ctrlDiv = "<div class=\"col-md-offset-2 col-md-10\">"; break;
            case ControlType.Image        : ctrlDiv = ""; break;
        }
        if (!string.IsNullOrEmpty(ctrlDiv))
        {
            html.AppendLine(ctrlDiv).
                    AppendLine(field.ToString()).
                    AppendLine((validation != null)?validation.ToString():"").
                    AppendLine("</div>");
        }
        return new MvcHtmlString(html.ToString());
    }
}

public class CtrlProperties
{
    public LabelProperties      Label      { get; set; }
    public ValidatorProperties  Validator  { get; set; }
    public EditorProperties     Editor     { get; set; }
    public UploaderProperties   Uploader   { get; set; }
    public ActionLinkProperties ActionLink { get; set; }
    public ButtonProperties     Button     { get; set; }
    public GlyphProperties      Glyph      { get; set; }
    public DropDownProperties   DropDown   { get; set; }
    public CheckBoxProperties   CheckBox   { get; set; }

    public CtrlProperties()
    {
        this.Editor     = null;
        this.Label      = null;
        this.Validator  = null;
        this.Uploader   = null;
        this.ActionLink = null;
        this.Button     = null;
        this.Glyph      = null;
        this.DropDown   = null;
        this.CheckBox   = null;
    }
}

public class PropertiesBase
{
    public virtual string DefaultClasses { get { return ""; } }
    public virtual string DefaultStyles  { get { return ""; } }
    public AddOrReplace ClassModifier    { get; set; }
    public AddOrReplace StyleModifier    { get; set; }
    public string       Classes          { get; set; }
    public string       Style            { get; set; }
    public bool         IsDisabled       { get; set; }
    public ControlFlags CtrlFlags        { get; set; }
    public string       AdditionalMarkup { get; set; }

    public PropertiesBase()
    {
        this.Classes       = string.Empty;
        this.Style         = string.Empty;
        this.IsDisabled    = false;
        this.CtrlFlags     = ControlFlags.IsInForm;
        this.ClassModifier = AddOrReplace.AddAfter;
    }

    protected string ApplyClassModifier(string defaultClasses, string newClasses, AddOrReplace modifier)
    {
        string classes = defaultClasses;
        if (!string.IsNullOrEmpty(newClasses))
        {
            switch (modifier)
            {
                case AddOrReplace.AddAfter  : classes = string.Format("{0} {1}", classes, newClasses); break;
                case AddOrReplace.AddBefore : classes = string.Format("{0} {1}", newClasses, classes); break;
                case AddOrReplace.Replace   : classes = newClasses; break;
                default                     : classes = string.Empty; break; // AddOrReplace.None
            }
        }
        return classes;
    }

    protected string NormalizeStyles(string styles)
    {
        styles = styles.TrimEnd(';');
        styles = (string.IsNullOrEmpty(styles))? styles : string.Concat(styles, ";");
        return styles;
    }

    public virtual object BuildAttributes()
    {
        return null;
    }
}

public class EditorProperties : PropertiesBase
{
    public override string DefaultClasses     { get { return "form-control"; } }
    public int    Width       { get; set; }
    public bool   IsInline    { get; set; }
    public bool HasActionLink { get; set; }
    public string Action      { get; set; }
    public string Controller  { get; set; }

    public EditorProperties() : base()
    {
        this.Width         = -1;
        this.IsInline      = false;
        this.HasActionLink = false;
        this.Action        = string.Empty;
        this.Controller    = string.Empty;
    }

    public override object BuildAttributes()
    {
        object attributes = null;
        // assume a standard label
        string classes    = this.DefaultClasses;
        // set the styles to the provided Style property
        string styles     = this.Style;
        classes = ApplyClassModifier(classes, this.Classes, this.ClassModifier);
        styles = NormalizeStyles(styles);
        if (this.Width > 0)
        {
            styles = string.Format("{0}width:{1};", styles, this.Width);
        }
        if (this.IsInline)
        {
            styles = string.Format("{0}display:inline:block;", styles);
        }
        // set our easy-type booleans
        bool isDisabled = this.IsDisabled;
        bool hasClasses = !string.IsNullOrEmpty(classes);
        bool hasStyle   = !string.IsNullOrEmpty(styles);
        if (hasClasses)
        {
            if (hasStyle && !isDisabled)
            {
                attributes = new {@class = classes, @style = styles };
            }
            else if (!hasStyle && isDisabled)
            {
                attributes = new { @class = classes, @disabled = "disabled" };
            }
            else if (hasStyle && isDisabled)
            {
                attributes = new { @class = classes, @disabled = "disabled", @style = styles };
            }
            else
            {
                attributes = new { @class = classes };
            }
        }
        else if (hasStyle)
        {
            if (isDisabled)
            {
                attributes = new { @disabled = "disabled", @style = styles };
            }
            else
            {
                attributes = new { @style = styles};
            }
        }
        else if (isDisabled)
        {
            attributes = new { @disabled = "disabled" };
        }
        attributes = new { htmlAttributes = attributes };
        return attributes;
    }
}

public class LabelProperties :PropertiesBase
{
    public override string DefaultClasses      { get { return "col-md-2 control-label"; } }
    public string LabelText     { get; set; }
    public bool   IsTransparent { get; set; }
    public bool   CheckRequired { get; set; }
    public string GlyphClass    { get; set; }

    public LabelProperties():base()
    {
        this.LabelText     = string.Empty;
        this.IsTransparent = false;
        this.CheckRequired = true;
    }

    public override object BuildAttributes()
    {
        object attributes = null;
        // assume a standard label
        string classes    = this.DefaultClasses;
        // set the styles to the provided Style property
        string styles     = this.Style;
        classes = ApplyClassModifier(classes, this.Classes, this.ClassModifier);
        styles = NormalizeStyles(styles);
        // set our easy-type booleans
        bool isDisabled = this.IsDisabled;
        bool hasClasses = !string.IsNullOrEmpty(classes);
        bool hasStyle   = !string.IsNullOrEmpty(styles);
        // build the attributes object
        if (hasClasses)
        {
            if (hasStyle && !isDisabled)
            {
                attributes = new {@class = classes, @style = styles };
            }
            else if (!hasStyle && isDisabled)
            {
                attributes = new { @class = classes, @disabled = "disabled" };
            }
            else if (hasStyle && isDisabled)
            {
                attributes = new { @class = classes, @disabled = "disabled", @style = styles };
            }
            else
            {
                attributes = new { @class = classes };
            }
        }
        else if (hasStyle)
        {
            if (isDisabled)
            {
                attributes = new { @disabled = "disabled", @style = styles };
            }
            else
            {
                attributes = new { @style = styles};
            }
        }
        else if (isDisabled)
        {
            attributes = new { @disabled = "disabled" };
        }
        return attributes;
    }
}

public class ValidatorProperties : PropertiesBase
{
    public override string DefaultClasses  { get { return "field-validation-valid text-danger"; } }
    public string ValidationMessage {  get; set; }

    public ValidatorProperties() : base()
    {
        this.ValidationMessage = string.Empty;
    }

    public override object BuildAttributes()
    {
        object attributes = null;
        // assume a standard label
        string classes    = this.DefaultClasses;
        // set the styles to the provided Style property
        string styles     = this.Style;
        classes = ApplyClassModifier(classes, this.Classes, this.ClassModifier);
        styles = NormalizeStyles(styles);
        bool hasClasses = !string.IsNullOrEmpty(classes);
        bool hasStyle   = !string.IsNullOrEmpty(styles);
        if (hasClasses)
        {
            if (hasStyle)
            {
                attributes = new {@class = classes, @style = styles };
            }
        }
        else if (hasStyle)
        {
            attributes = new { @style = styles };
        }
        return attributes;
    }
}


I can also do things like this:
HTML
// if the field is "required", the same code as above will perform special markup on the label
@Html.EditForEx(model => model.NameRequired)

// if the field is required, but I don't want the markup...
@Html.EditForEx(model => model.NameRequired, new CtrlProperties(){Label=new LabelProperties(){CheckRequired=false}})

//if I want the field disabled...
@Html.EditForEx(model=>model.Name, new CtrlProperties(){ Editor = new EditorProperties(){ IsDisabled = true} })


I can change any related component by instantiating the "properties" object for that component, and changing the properties in that object. If a related properties object is not instantiated in the method call, the default (MVC) version of the component is created and used.

If a different web app requires a different appearance, I simply change the required "properties classes, and the entire site reflects that appearance without any extra work in the middle-tier or outward-facing code.

I'm not saying this is the best approach, but it works really well. I did all this despite the fact that I typically just use the basic method 99.9% of the time. As you might guess, I have similar code for the other control types.
".45 ACP - because shooting twice is just silly" - JSOP, 2010
-----
You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010
-----
When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013


modified 14-Dec-17 13:00pm.

GeneralRe: Overengineering 101 Pin
MarkTJohnson14-Dec-17 7:31
professionalMarkTJohnson14-Dec-17 7:31 
GeneralRe: Overengineering 101 Pin
#realJSOP14-Dec-17 7:52
professional#realJSOP14-Dec-17 7:52 
GeneralRe: Overengineering 101 Pin
Richard Deeming14-Dec-17 8:02
mveRichard Deeming14-Dec-17 8:02 
GeneralRe: Overengineering 101 Pin
BillWoodruff14-Dec-17 8:34
professionalBillWoodruff14-Dec-17 8:34 
GeneralRe: Overengineering 101 Pin
R. Giskard Reventlov14-Dec-17 9:10
R. Giskard Reventlov14-Dec-17 9:10 
GeneralRe: Overengineering 101 Pin
Slacker00714-Dec-17 9:28
professionalSlacker00714-Dec-17 9:28 
GeneralRe: Overengineering 101 Pin
#realJSOP14-Dec-17 10:30
professional#realJSOP14-Dec-17 10:30 
GeneralRe: Overengineering 101 Pin
Slacker00714-Dec-17 10:56
professionalSlacker00714-Dec-17 10:56 
GeneralRe: Overengineering 101 Pin
dandy7214-Dec-17 11:03
dandy7214-Dec-17 11:03 
JokeRe: Overengineering 101 Pin
Daniel Pfeffer14-Dec-17 20:35
professionalDaniel Pfeffer14-Dec-17 20:35 
JokeRe: Overengineering 101 Pin
Dar Brett15-Dec-17 1:36
Dar Brett15-Dec-17 1:36 
GeneralRe: Overengineering 101 Pin
Eddy Vluggen14-Dec-17 10:22
professionalEddy Vluggen14-Dec-17 10:22 
GeneralRe: Overengineering 101 Pin
#realJSOP14-Dec-17 10:26
professional#realJSOP14-Dec-17 10:26 
GeneralRe: Overengineering 101 Pin
Eddy Vluggen14-Dec-17 10:29
professionalEddy Vluggen14-Dec-17 10:29 
GeneralRe: Overengineering 101 Pin
Marc Clifton14-Dec-17 12:42
mvaMarc Clifton14-Dec-17 12:42 
GeneralRe: Overengineering 101 Pin
#realJSOP14-Dec-17 13:37
professional#realJSOP14-Dec-17 13:37 
GeneralRe: Overengineering 101 Pin
Jeremy Falcon14-Dec-17 20:28
professionalJeremy Falcon14-Dec-17 20:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.