2011-09-21 12 views
7

Nie jestem guru w składni maszyn Razor, ale staram się zbudować ogólną bibliotekę za pomocą płynnych elementów interfejsu GUI Telerik.Razor Func <obiekt, obiekt> zmieszany z MvcHtmlString

Mam następujące kawałki (w przybliżeniu):

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

oraz:

/// <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 -->"); 
    } 
} 

Mam też zestaw HTML metod rozszerzenie, które zwracają MvcHtmlString jest. Jednym z przykładów jest (uproszczony):

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)); 
     } 
} 

Następnie w moim .cshtml pliku, I wykonaj następujące czynności:

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

który wzywa public MyBox Content(Func<object, object> value), i działa. Podobnie, gdy próbuję następujące:

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

To szczęśliwie nazywa public MyBox Content(MvcHtmlString content) i działa zgodnie z oczekiwaniami.

Jednak, gdy próbuję wykonać następujące czynności, nie mogę objąć głowy, jak działa silnik kompilatora Razor. Jak mogę zmusić go do powrotu sumę

  • @<h1>Hello World! This is Gui().Box()</h1> (co jest Func)
  • Html.GuiFieldContainerHeading("SubHeading 1") (który jest MvcHtmlString)

albo jako jeden obiekt (czy to Func, MvcHtmlString ?, niezależnie, czy lista obiektów chciałbym napisać rodzajowy składni Razor wewnątrz listy parametrów do funkcji Content w mojej klasie myBOX, tak:

@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> 
         ) 
     ) 
} 

Czy jestem na dobrej drodze, czy też jest o wiele prostszy sposób robienia tego, co chcę? Chcę zebrać wszystkie "wspólne elementy GUI" w naszym systemie we wspólnej bibliotece DLL, więc nie każdy programista w mojej organizacji musi wymyślić nowe koło w każdym projekcie.

Każda pomoc doceniona.


OK, kolejnym problemem:

Mam uogólnione Box do pojemnika i stworzył dwie podklasy, pudełko i HighlightArea. Jednakże, używając następującego kodu, kompilator Razor wykopuje mnie z wiadomością

bloki Inline znaczników (@ <p> Content </p >) nie mogą być zagnieżdżone. Dozwolony jest tylko jeden poziom wbudowanych znaczników.

Kod nie działa, to:

@(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> 
       ) 

Czy mamy obejście tego? Czy moje podejście jest niewykonalne?

+1

Twój przykład zawierający 'This is Gui(). Box()' jest nieco mylący. Wygląda na to, że zawiera jakiś kod C#, ale prawdopodobnie nie powinien. – Codo

+0

Dzięki. Zaktualizowałem to pytanie, aby uniknąć konfrontacji. Jakieś myśli na temat inne niż zamieszanie? –

+0

Następny problem (dzięki, Bill The Lizard, za aktualizację pytania ...:)) ... Wszelkie przemyślenia na ten temat (patrz pytanie) –

Odpowiedz

7

Możesz użyć znacznika <text>, aby połączyć wszystko w jeden parametr.

@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> 
     ) 
    ) 
} 

Chyba Twój przykład nie jest tak naprawdę działa. Jeśli się nie mylę można go dostać pracę tak:

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

Ale tag <text> wydaje się łatwiejsze.

+0

Pracował jak urok. Dzięki! :) –

Powiązane problemy