2011-09-21 14 views
7

No soy un gurú en la sintaxis de Razor, pero trato de crear una biblioteca genérica utilizando un estilo fluido con los componentes de GUI de Telerik.Razor Func <objeto, objeto> mezclado con MvcHtmlString

I tienen las siguientes piezas (aproximadamente):

public static MyBox Box(this HtmlHelper helper) 
{ 
    return new MyBox(helper.ViewContext); 
} 

y:

/// <summary> 
/// http://geekswithblogs.net/shaunxu/archive/2010/04/10/lt-gt-htmlencode-ihtmlstring-and-mvchtmlstring.aspx 
/// </summary> 
public class MyBox : IHtmlString 
{ 
    private readonly ViewContext _viewContext; 
    private string _content; 
    private string _title; 

    public MyBox(ViewContext viewViewContext) 
    { 
     _viewContext = viewViewContext; 
    } 

    /// <summary> 
    /// See: http://haacked.com/archive/2011/02/27/templated-razor-delegates.aspx 
    /// </summary> 
    /// <param name="value"></param> 
    /// <returns></returns> 
    public MyBox Content(Func<object, object> value) 
    { 
     _content = value.DynamicInvoke(_viewContext).ToString(); 
     return this; 
    } 

    /// <summary> 
    /// See: http://haacked.com/archive/2011/02/27/templated-razor-delegates.aspx 
    /// </summary> 
    /// <param name="values"></param> 
    /// <returns></returns> 
    public MyBox Content(params Func<object, object>[] values) 
    { 
     foreach (var value in values) 
     { 
      _content += value.DynamicInvoke(_viewContext).ToString(); 
     } 
     return this; 
    } 

    public MyBox Content(MvcHtmlString content) 
    { 
     _content = content.ToString(); 
     return this; 
    } 

    public MyBox Title(string title) 
    { 
     _title = title; 
     return this; 
    } 

    public string ToHtmlString() 
    { 
     using (var stringWriter = new StringWriter()) 
     { 
      WriteHtml((TextWriter)stringWriter); 
      return stringWriter.ToString(); 
     } 
    } 

    public void Render() 
    { 
     using (var writer = new HtmlTextWriter(_viewContext.Writer)) 
      WriteHtml(writer); 
    } 

    protected virtual void WriteHtml(TextWriter writer) 
    { 
     writer.WriteLine("<!-- START BOX -->"); 
     writer.WriteLine("<h1>" + _title + "</h1>)); 
     writer.WriteLine(_content); 
     writer.WriteLine("<!-- END BOX -->"); 
    } 
} 

I también tiene un conjunto de métodos de extensión HTML que devuelven MvcHtmlString de. Un ejemplo es (simplificado):

public static class GuiElementExtensions 
    { 
     private const string FieldContainerHeadingTemplate = @" 
<tr><th style=""text-align:left"" colspan=""2"">{0}</th></tr> 
"; 

    public static MvcHtmlString GuiFieldContainerHeading(this HtmlHelper helper, string text) 
     { 
      return new MvcHtmlString(String.Format(FieldContainerHeadingTemplate, text)); 
     } 
} 

Entonces, en mi archivo .cshtml, hago lo siguiente:

@using (Html.BeginForm()) 
     { 
      @(Html.Gui() 
         .Box() 
         .Title("Hello World!") 
         .Content(
           @<h1>Hello World! This is the cool Gui.Box</h1> 
         ) 
     ) 
} 

que llama a public MyBox Content(Func<object, object> value), y trabaja. Del mismo modo, cuando intento el siguiente:

@using (Html.BeginForm()) 
     { 
      @(Html.Gui() 
         .Box() 
         .Title("Hello World!") 
         .Content(
           Html.GuiFieldContainerHeading("SubHeading 1") 
         ) 
     ) 
} 

Se llama felizmente public MyBox Content(MvcHtmlString content) y funciona como se esperaba.

Pero, sin embargo, cuando trato de hacer lo siguiente, no puedo entender cómo funciona el motor del compilador Razor. ¿Cómo consigo que vuelva la suma de

  • @<h1>Hello World! This is Gui().Box()</h1> (que es un Func)
  • Html.GuiFieldContainerHeading("SubHeading 1") (que es un MvcHtmlString)

ya sea como un objeto (ya sea un Func, MvcHtmlString ?, lo que sea, o una lista de objetos me gustaría escribir la sintaxis Razor genérica dentro de la lista de parámetros a la función de contenido en mi clase MyBox, así:

@using (Html.BeginForm()) 
     { 
      @(Html.Gui() 
         .Box() 
         .Title("Hello World!") 
         .Content(
           @<h1>Hello World! This is Gui().Box()</h1> 
           Html.GuiFieldContainerHeading("SubHeading 1") 
       Html.TextBoxFor(model => model.Name) 
       @<h2>Hello there!</h2> 
         ) 
     ) 
} 

¿Estoy en el camino correcto o hay una manera mucho más simple de hacer lo que quiero? Quiero reunir todos los "elementos comunes de interfaz gráfica de usuario" en nuestro sistema en una DLL común, por lo que no todos los desarrolladores de mi organización deben reinventar la rueda en cada proyecto.

Cualquier ayuda apreciada.


bien, siguiente problema:

me han generalizado la caja en un recipiente, y creó dos subclases, la caja y HighlightArea. Sin embargo, usando el siguiente código, el compilador de afeitar me echa con el mensaje

bloques línea de marcado (p @ < > contenido </p >) no se pueden anidar. Solo se permite un nivel de marcado en línea.

El código no funciona, es:

@(Html.Gui() 
       .Box() 
       .Title("BoxTitle") 
       .Content(@<text> 
         <h1>Hello World! This is the box content</h1> 
         @Html.GuiFieldContainerHeading("This is the heading") 
         @(Html.Gui().HighlightArea() 
           .Content(
           @Html.ValidationSummary() 
           @<h1>Jalla</h1> 
          ) 
         ) 
         </text> 
       ) 

¿Tenemos una solución para esto? ¿O mi enfoque no es factible?

+1

Su ejemplo que contiene 'Esto es Gui(). Caja()' es un poco confuso. Parece que contiene algún código C# pero probablemente no se supone que lo sea. – Codo

+0

Gracias. He actualizado la pregunta para evitar confuciones. ¿Alguna idea sobre la pregunta que no sea la confusión? –

+0

siguiente problema (gracias, Bill el lagarto, para la actualización de la pregunta ...:)) ... Alguna idea de que (véase la pregunta) –

Respuesta

7

usted podría utilizar la etiqueta <text> combinar todo en un solo parámetro.

@using (Html.BeginForm()) 
{ 
    @(Html.Gui() 
     .Box() 
     .Title("Hello World!") 
     .Content(
      @<text> 
       <h1>Hello World! This is Gui.Box</h1> 
       @Html.GuiFieldContainerHeading("SubHeading 1") 
       @Html.TextBoxFor(model => model.Name) 
       <h2>Hello there!</h2> 
      </text> 
     ) 
    ) 
} 

Creo que su ejemplo no funciona realmente. Si no me equivoco se podía conseguir que funcione de esta manera:

@<h1>Hello World! This is Gui.Box</h1> 
+ Html.GuiFieldContainerHeading("SubHeading 1") 
+ Html.TextBoxFor(model => model.Name) 
+ @<h2>Hello there!</h2> 

Pero la etiqueta <text> parece más fácil.

+0

funcionó de maravilla. ¡Gracias! :) –

Cuestiones relacionadas