Как заставить этот Razor View работать как ASPX? - PullRequest
3 голосов
/ 13 октября 2011

Я изо всех сил пытался получить частичный вид, работающий в Razor. Движок View не может понять смысл приведенного ниже кода, но он прост с использованием механизма ASPX View. Может кто-нибудь показать мне, как заставить это работать с Razor? Обратите внимание, что я просто пишу календарь, поэтому тег

появляется в конце каждой недели. Первым признаком проблемы является то, что код Razor не будет форматироваться в редакторе VS, и он жалуется, что в блоке while отсутствует закрывающая скобка. Я перепробовал все виды комбинаций, даже используя делегата. (Я думаю, что причиной проблемы может быть условный тег TR, потому что он выделен как ошибка, потому что он не закрыт.)

Бритва (не работает)

 <table class="calendarGrid">
    <tr class="calendarDayNames">
        <th>Monday</th>
        <th>Tuesday</th>
        <th>Wednesday</th>
        <th>Thursday</th>
        <th>Friday</th>
        <th>Saturday</th>
        <th>Sunday</th>
    </tr>
    @{
        var loopDate = gridStartDate;
    }
    @while (loopDate <= gridEndDate)
    {
        if (loopDate.DayOfWeek == DayOfWeek.Monday)
        {
            <tr class="calendarWeek">
        }
            <td class="calendarDay">
                <span class="calendarDayNumber">@loopDate.Day</span>
                @if (Model.AllCalendarDays.ContainsKey(loopDate.Date))
                {
                    foreach (var ev in Model.AllCalendarDays[loopDate.Date])
                    {
                        <span class="calendarEvent">@ev.Venue</span>
                    }
                }
            </td>
            @{ 
                loopDate = loopDate.AddDays(1);
                @if (loopDate.DayOfWeek == DayOfWeek.Monday)
                {
                    </tr>
                }
            }
    }

ASPX (работает)

  <table class="calendarGrid">
    <tr class="calendarDayNames">
        <th>Monday</th>
        <th>Tuesday</th>
        <th>Wednesday</th>
        <th>Thursday</th>
        <th>Friday</th>
        <th>Saturday</th>
        <th>Sunday</th>
    </tr>
    <% 
        var loopDate = gridStartDate;

        while (loopDate <= gridEndDate)
        {
            if (loopDate.DayOfWeek == DayOfWeek.Monday)
            {
    %>
    <tr class="calendarWeek">
        <%} %>
        <td class="calendarDay">
            <span class="calendarDayNumber">
                <%: loopDate.Day %></span>
            <% if (Model.AllCalendarDays.ContainsKey(loopDate.Date))
               {
                   foreach (var ev in Model.AllCalendarDays[loopDate.Date])
                   { %>
            <span class="calendarEvent">
                <%: ev.Venue %></span>
            <%  }
               } %>
        </td>
        <%  {
                loopDate = loopDate.AddDays(1);
                if (loopDate.DayOfWeek == DayOfWeek.Monday)
                { %>
    </tr>
    <% }
            }
        } %>
</table>

Рабочее решение в Razor, основанное на предложении модели представления @ jgauffin и уродливом необработанном html-решении @ dommer. В сочетании они почти эстетически приемлемы. :)

У модели теперь есть итератор

    public IEnumerable<Tuple<DateTime, IList<CalendarEventDto>>> GridItems()
    {
        var loopDate = GridStartDate;
        while (loopDate <= GridEndDate)
        {
            yield return new Tuple<DateTime, IList<CalendarEventDto>>(loopDate.Date, AllCalendarDays[loopDate.Date]);
            loopDate = loopDate.AddDays(1);
        }
    }

Хорошо, Tuple ленив, но я, вероятно, создам другую модель для хранения более сложной информации о дате и событиях (IsPast / greyed и т. Д.).

Скучный вид

           @foreach (var item in Model.GridItems())
        {
            if (item.Item1.DayOfWeek == DayOfWeek.Monday)
            { 
                @Html.Raw("<tr class=\"calendarWeek\">");
            }
            @Html.Raw("<td class=\"calendarDay\">");
            @Html.Raw(string.Format("<span class=\"calendarDayNumber\">{0}</span>", item.Item1.Day));
            foreach (var ev in item.Item2)
            {
                @Html.Raw(string.Format("<span class=\"calendarEvent\">{0}</span>", Server.HtmlEncode(ev.Venue)));
            }
            @Html.Raw("</td>");
            if (item.Item1.DayOfWeek == DayOfWeek.Sunday)
            {
                @Html.Raw("</tr>");
            }
        }

Обратите внимание, что когда я переформатирую источник View в VS, он получает вопиющую вкладку, с оператором if, имеющим около 10 вкладок слева от него, но нет предупреждений компиляции, и он делает то, что я хочу. Не приятно или просто. Я думаю, что разработчики Razor должны обеспечить некоторую поддержку явного разбиения и разбивки на код и разметку, чтобы, когда анализатор не мог проанализировать его однозначно, мы могли сказать ему, что мы собирались.

@ Решение Эндрю Медсестры Эндрю «работает над созданием команды ASP.Net для создания анализатора Razor!». Его решение работает нормально, но по-прежнему выдает предупреждения компилятора и, очевидно, сбивает с толку Visual Studio, потому что код не может быть переформатирован без попадания в большую строку в несколько строк:

       <tbody>
        @foreach (var calDay in Model.GridItems())
        {
            if (calDay.DayOfWeek == DayOfWeek.Monday)
            { 
                @:<tr class="calendarWeek">
            } 
            <td class="calendarDay">
                <span class="calendarDayNumber">@calDay.Day</span> 
                @foreach (var ev in calDay.CalendarEvents) 
                { 
                    <span class="calendarEvent">@ev.Venue</span> 
                } 
            </td> 
            if (calDay.DayOfWeek == DayOfWeek.Sunday)
            { 
                @:</tr>                 
            }
        }
    </tbody>

Ответы [ 4 ]

4 голосов
/ 13 октября 2011

Основными проблемами здесь были следующие строки:

if (loopDate.DayOfWeek == DayOfWeek.Monday)
{
    <tr class="calendarWeek">
}

...

@if (loopDate.DayOfWeek == DayOfWeek.Monday)
{
    </tr>
}

Проблема в том, что Razor использует теги для определения начала и конца разметки.Так как вы не закрыли тег "tr" внутри первого if, он фактически не переключается обратно на код, поэтому он не видит "}" как код.Решение состоит в том, чтобы использовать «@:», что позволяет вам поместить строку разметки без учета тегов.Поэтому замена этих строк на это должна работать и быть более краткой, чем использование Html.Raw:

if (loopDate.DayOfWeek == DayOfWeek.Monday)
{
    @:<tr class="calendarWeek">
}

...

@if (loopDate.DayOfWeek == DayOfWeek.Monday)
{
    @:</tr>
}
1 голос
/ 13 октября 2011

Я бы переместил всю логику в модель представления, которая оставляет следующий код в вашем представлении:

@while (Model.MoveNext())
{
    @Model.WeekHeader
        <td class="calendarDay">
            <span class="calendarDayNumber">@Model.DayNumber</span>
            @foreach (var ev in Model.CurrentDayEvents)
            {
                <span class="calendarEvent">@ev.Venue</span>
            }
        </td>
    @Model.WeekFooter
}

И новую модель:

public class CalendarViewModel
{
    private DateTime _currentDate;

    public string WeekHeader
    {
        get
        {
            return _currentDate.DayOfWeek == DayOfWeek.Monday ? "<tr class="calendarWeek">" : "";
        }
    }
    public string WeekFooter
    {
        get
        {
            return _currentDate.DayOfWeek == DayOfWeek.Monday ? "</tr>" : "";
        }
    }

    public IEnumerable<DayEvent> 
    { 
        get 
        { 
            return AllCalendarDays.ContainsKey(loopDate.Date) ? AllCalendarDays[loopDate.Date] ? new List<DayEvent>();
        }
    }

public bool MoveNext()
{
    if (_currentDate == DateTime.MinValue)
    {
        _currentDate = gridStartDate;
        return true;
    }

    _currentDate = _currentDate.AddDays(1);
    return _currentDate <= gridEndDate;
}
}
1 голос
/ 13 октября 2011

ОСНОВНОЕ РЕДАКТИРОВАНИЕ: Хорошо, что произойдет, если вы сделаете это?

<table class="calendarGrid">
<tr class="calendarDayNames">
    <th>Monday</th>
    <th>Tuesday</th>
    <th>Wednesday</th>
    <th>Thursday</th>
    <th>Friday</th>
    <th>Saturday</th>
    <th>Sunday</th>
</tr>
@{
var loopDate = gridStartDate;
while (loopDate <= gridEndDate)
{
    if (loopDate.DayOfWeek == DayOfWeek.Monday)
    {
        @Html.Raw("<tr class=\"calendarWeek\">");
    }
    @Html.Raw("<td class=\"calendarDay\">");
    @Html.Raw("<span class=\"calendarDayNumber\">" + loopDate.Day + "</span>");
    if (Model.AllCalendarDays.ContainsKey(loopDate.Date))
    {
        foreach (var ev in Model.AllCalendarDays[loopDate.Date])
        {
            @Html.Raw("<span class=\"calendarEvent\">" + ev.Venue + "</span>");
        }
    }
    @Html.Raw("</td>");
    loopDate = loopDate.AddDays(1);
    if (loopDate.DayOfWeek == DayOfWeek.Monday)
    {
        @Html.Raw("</tr>");
    }
}
}

0 голосов
/ 13 октября 2011

Вы пытались добавить <text> теги вокруг содержимого блоков?

Alternatively, Razor also allows you to use a text element to explicitly identify content

Я думаю, что анализ Razor работает только тогда, когда очевидно, где заканчиваются блоки. Это может смущать тот факт, что у вас есть if, td и еще какой-то код внутри блока.

Подробнее об этом здесь: http://weblogs.asp.net/scottgu/archive/2010/12/15/asp-net-mvc-3-razor-s-and-lt-text-gt-syntax.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...