views:

56

answers:

2

Hi! Could someone point me in the right direction on how would I go about creating htmlhelpers that you could call in the view something like the code below.

   <% using (Html.BeginSvg())
   {%>
   <% using (Html.BeginGroup("Group1")) {%>
        <%= Html.SvgLine("Line1").Class("blueLine").Style("stroke-width:2px").X1(25).Y1(25).X2(25).Y2(25).Transform().Scale(-2)%>
        <%= Html.SvgLine("Line1").Class("blueLine").Style("stroke-width:2px").X1(100).Y1(25).X2(100).Y2(125).Transform().Scale(-2)%>
   <%} %>
   <%= Html.SvgRect("box").Class("redBox").X(12).Y(10).Width(234).Height(200) %>
<%} %>

Is it possible? is it sane? :) is there something like this already implemented?

Cheers Si

A: 

I don't know if it's been done but Fluent Interfaces are awesome...here's a very basic implementation for you.

public static class SvgLineHelper {
    public static SvgLine SvgLine(this HtmlHelper helper, string name) {
        return new SvgLine(name);
    }
}

public class SvgLine {
    string _name;
    int _x;
    int _y;
    int _width;
    int _height;
    IList<string> _styles;

    public SvgLine(string name) {
        _styles = new List<string>();
        _name = name;
    }

    public static SvgLine Create(string name) {
        return new SvgLine(name);
    }

    public SvgLine X(int x) {
        this._x = x;
        return this;
    }

    public SvgLine Width(int width) {
        this._width = width;
        return this;
    }

    public SvgLine Style(string style) {
        this._styles.Add(style);
        return this;
    }

    public override string ToString() {
        //create your string from this object here
        return string.Format("x:{0}, width:{1}, style:{2}", _x, _width, _styles[0]);
    }
}

And here's how you use it in your html

<% Html.SvgLine("test").X(100).Width(50).Style("stroke-width:2px").ToString() %>

You have to call the tostring method as the last call (or another method that finalizes your fluent interface - the one that returns a string representation of your object)

BuildStarted
Hi Morder, definatly pointed me in the right direction there, thanks.
Simon Owen
Using this method would there be any way to build logic in, i.e. <% Html.SvgLine("test").X(100).XIf you have already set X it makes no sense to set it again.
Simon Owen
Not really, since it's just a regular function call and not really subject to those types of rules...you can ignore any subsequent steps, however, by checking if the internal value is set first.
BuildStarted
A: 

Html helpers called with <%= must return string or MvcHtmlString. So the API you propose won't work unless you add a ToString or something at the end, like:

<%= Html.SvgLine("Line1").Class("blueLine").ToMvcHtmlString() %>

Alternately, you could pass a fluent config object as an argument to SvgLine:

<%= Html.SvgLine(With().Name("Line1").Class("blueLine")) %>

Either way would work. Pick whichever you like.

Craig Stuntz
I don't think that you have to actually make/call ToString method. object.ToString() should be called automatically, all you have to do is override it.
Necros
@Necros: Not for `MvcHtmlString`, no. And I'm guessing that he's returning angle brackets, so that is what he needs for ASP.NET 4.
Craig Stuntz
If you want to use `<%:`, then yes, you need `MvcHtmlString`. For `<%=`, string will do.
Necros
Well, right, but there is *no* good reason to not support `<%:`
Craig Stuntz