Razor - как преобразовать содержимое в переменную

Как отобразить часть Html в переменной в Razor? В Spark я использовал для записи следующий код:

<content var="t">
    <a class="tab" href="">Tab name</a>
</content>

<content var="tc">
    <div class="tabcontent">
        <p>Here goes tab content</p>
    </div>
</content>

!{tabs(t, tc)}

две переменные передаются макросу, который выполняет всю приятную упаковку содержимого в лист вкладок.

Какой лучший способ сделать то же самое в Razor?

Обновление: Я думаю, что понял.

В Razor конструкцией @<text>...</text> может быть пользователь для создания лямбда-выражений, которые могут быть повторно использованы позже, что является расширенным эквивалентом назначения части HTML переменной. Вышеприведенный пример может быть реализован следующим образом:

Func<int, object> t =
    @<text>
        <a class="tab" href="">Tab name</a>
    </text>;

Func<int, object> tc =
    @<text>
        <div class="tabcontent">
            <p>Here goes tab content</p>
        </div>
    </text>;


@tabs(t(0), tc(0))

Я просто не могу понять, как писать без параметров lambdas (Func<object>). параметр int в обоих lambdas выше - это фиктивный. Кажется, что Razor требует один параметр (и уже создает переменную "item", чтобы обозначить ее внутри выражения).

Ответы

Ответ 1

В принципе, OP уже ответила на проблему, потому что вы могли бы сделать что-то вроде:

@{
   Func<dynamic, object> a = @<text>
       Some Text        
   </text>;
   @a(new object())
}    

Если текст относится только к одной строке, вы можете даже использовать оператор "@:", просто remmebr, чтобы на следующей строке была точка с запятой (или, если ей нужны любые закрывающие скобки или скобки), как в следующем примере

@{
   Func<dynamic, object> a = @: Some Text
   ;    
   @a(new object())
}

Однако вы можете записать его непосредственно в виде строки, если хотите

@{
    string a = ((Func<dynamic, object>)(@<text>
                    Some Text
                </text>))("").ToString();
    @a //Output directly as a string        
}

Вы можете даже инкапсулировать его в функцию:

@functions{
     public string ToString(Func<dynamic, object> input)
     {
          return input("").ToString();
     }
}

@{
    string a = ToString(@<text>
                    Some Text
               </text>);
    @a //Output directly as a string        
 }

Ответ 2

Возможно, вы можете использовать HtmlString? Я не думаю, что мне это очень нравится, но вот то, что я бы постарался как точный перевод того, что у вас есть...

@{
    var t = new HtmlString("<a class='tab' href=''>Tab name</a>");
    var tc = new HtmlString("<div class='tabcontent'><p>Here goes tab content</p></div>");
}
@tabs(t, tc)

Итак... Я не знаю, как выглядит ваш макрос Spark, но это похоже на возможность использовать помощника в Razor. У вас может быть что-то вроде:

@helper Tabs(string tabName, string tabContent)
{
    <!-- some wrapper code -->   
    <a class="tab" href="">@(tabName)</a>
    <!-- some more wrapper code -->
    <div class="tabcontent">
        <p>@(tabContent)</p>
    </div>
    <!-- still more wrapper code -->
}

Затем вы вызываете это из вашей страницы следующим образом:

@Tabs("Tab Name", "Here goes tab content")

Ответ 3

На всякий случай, если кто-то еще найдет этот пост (как и я), Энди Обновление почти там. В дополнение к приведенному примеру все, что вам нужно сделать для доступа к 'int' в приведенном примере, это ссылка @item. В блоках @<text></text> переменная item содержит модель, на которую она была вызвана.

Вот пример того, как его можно использовать:

@model PageData

@{
    Func<Customer, object> sayHi = 
        @<text>
             <li>Hello @(item.FirstName)!</li>
         </text>;
}

<ul>
    @foreach(var customer in Model.Customers)
    {
        sayHi(customer);
    }
</ul>

В большинстве случаев вам, вероятно, следует использовать частичный вид вместо такой функции. Но в редких случаях, когда частичное представление невозможно (например, при использовании библиотеки RazorEngine), это работает.

Ответ 4

Если у вас есть вид IHtmlContentBuilder в представлении Razor, вы можете использовать эти расширения.

    public static IHtmlContentBuilder AppendRazor(this IHtmlContentBuilder htmlContentBuilder, Func<IHtmlContent, dynamic> lamda)
    {
        var html = lamda(null);
        return htmlContentBuilder.AppendHtml(html);
    }

    public static IHtmlContentBuilder AppendRazor<T>(this IHtmlContentBuilder htmlContentBuilder, Func<T, IHtmlContent> lamda, T model)
    {
        var html = lamda(model);
        return htmlContentBuilder.AppendHtml(html);
    }

Использование

@{
    HtmlContentBuilder contentBuilder = new HtmlContentBuilder();
    contentBuilder.AppendRazor(@<text><p>Hello @Model.Name<p></text>);
    contentBuilder.AppendRazor(@<text><p>Hello @item.CustomerName<p></text>, customer);
}
<div>
     @contentBuilder
</div>