Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create Extension Method to Produce Open & Closing Tags like Html.BeginForm()

I wonder if it's possible to create an extension method which has functionality & behaviour similar to Html.BeginForm(), in that it would generate a complete Html tag, and I could specificy its contents inside <% { & } %> tags.

For example, I could have a view like:

<% using(Html.BeginDiv("divId")) %>
<% { %>
    <!-- Form content goes here -->
<% } %>

This capability would be very useful in the context of the functionality I'm trying to produce with the example in this question

This would give me the ability to create containers for the types that I'll be

<% var myType = new MyType(123, 234); %>
<% var tag = new TagBuilder("div"); %>

<% using(Html.BeginDiv<MyType>(myType, tag) %>
<% { %>
    <!-- controls used for the configuration of MyType  -->
    <!-- represented in the context of a HTML element, e.g.:  -->

    <div class="MyType" prop1="123" prop2="234">
        <!-- add a select here -->
        <!-- add a radio control here -->
        <!-- whatever, it represents elements in the context of their type -->
    </div>

<% } %>

I realise this will produce invalid XHTML, but I think there could be other benefits that outweigh this, especially since this project doesn't require that the XHTML validate to the W3C standards.

Thanks

Dave

like image 263
DaveDev Avatar asked Mar 12 '10 21:03

DaveDev


People also ask

What is extension method with example?

An extension method is actually a special kind of static method defined in a static class. To define an extension method, first of all, define a static class. For example, we have created an IntExtensions class under the ExtensionMethods namespace in the following example.

Can we create extension method for sealed class?

Sealed classes are used to restrict the users from inheriting the class. A class can be sealed by using the sealed keyword. The keyword tells the compiler that the class is sealed, and therefore, cannot be extended. No class can be derived from a sealed class.

What is extension method how it is achieved?

Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are static methods, but they're called as if they were instance methods on the extended type.

What is extension method in Java?

In object-oriented computer programming, an extension method is a method added to an object after the original object was compiled. The modified object is often a class, a prototype or a type. Extension methods are features of some object-oriented programming languages.


1 Answers

Not quite sure how much value this has over simply defining a <div> element, but something like so

/// <summary>
/// Represents a HTML div in an Mvc View
/// </summary>
public class MvcDiv : IDisposable
{
    private bool _disposed;
    private readonly ViewContext _viewContext;
    private readonly TextWriter _writer;

    /// <summary>
    /// Initializes a new instance of the <see cref="MvcDiv"/> class.
    /// </summary>
    /// <param name="viewContext">The view context.</param>
    public MvcDiv(ViewContext viewContext) {
        if (viewContext == null) {
            throw new ArgumentNullException("viewContext");
        }
        _viewContext = viewContext;
        _writer = viewContext.Writer;
    }

    /// <summary>
    /// Performs application-defined tasks associated with 
    /// freeing, releasing, or resetting unmanaged resources.
    /// </summary>
    public void Dispose()
    {
        Dispose(true /* disposing */);
        GC.SuppressFinalize(this);
    }

    /// <summary>
    /// Releases unmanaged and - optionally - managed resources
    /// </summary>
    /// <param name="disposing"><c>true</c> to release both 
    /// managed and unmanaged resources; <c>false</c> 
    /// to release only unmanaged resources.</param>
    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            _disposed = true;
            _writer.Write("</div>");
        }
    }

    /// <summary>
    /// Ends the div.
    /// </summary>
    public void EndDiv()
    {
        Dispose(true);
    }
}


/// <summary>
/// HtmlHelper Extension methods for building a div
/// </summary>
public static class DivExtensions
{
    /// <summary>
    /// Begins the div.
    /// </summary>
    /// <param name="htmlHelper">The HTML helper.</param>
    /// <returns></returns>
    public static MvcDiv BeginDiv(this HtmlHelper htmlHelper)
    {
        // generates <div> ... </div>>
        return DivHelper(htmlHelper, null);
    }

    /// <summary>
    /// Begins the div.
    /// </summary>
    /// <param name="htmlHelper">The HTML helper.</param>
    /// <param name="htmlAttributes">The HTML attributes.</param>
    /// <returns></returns>
    public static MvcDiv BeginDiv(this HtmlHelper htmlHelper, IDictionary<string, object> htmlAttributes)
    {
        // generates <div> ... </div>>
        return DivHelper(htmlHelper, htmlAttributes);
    }

    /// <summary>
    /// Ends the div.
    /// </summary>
    /// <param name="htmlHelper">The HTML helper.</param>
    public static void EndDiv(this HtmlHelper htmlHelper)
    {
        htmlHelper.ViewContext.Writer.Write("</div>");
    }

    /// <summary>
    /// Helps build a html div element
    /// </summary>
    /// <param name="htmlHelper">The HTML helper.</param>
    /// <param name="htmlAttributes">The HTML attributes.</param>
    /// <returns></returns>
    private static MvcDiv DivHelper(this HtmlHelper htmlHelper, IDictionary<string, object> htmlAttributes)
    {
        TagBuilder tagBuilder = new TagBuilder("div");
        tagBuilder.MergeAttributes(htmlAttributes);

        htmlHelper.ViewContext.Writer.Write(tagBuilder.ToString(TagRenderMode.StartTag));
        MvcDiv div = new MvcDiv(htmlHelper.ViewContext);

        return div;
    }
}

and use like so

<% using (Html.BeginDiv(new Dictionary<string, object>{{"class","stripey"}}))
{ %>
       <p>Content Here</p>
<% } %>

will render

<div class="stripey">
    <p>Content Here</p>
</div>

or without html attributes

<% using (Html.BeginDiv())
{ %>
       <p>Content Here</p>
<% } %>
like image 197
Russ Cam Avatar answered Oct 09 '22 17:10

Russ Cam