Общий частичный вид: как установить общий класс в качестве модели? - PullRequest
12 голосов
/ 17 мая 2009

Я пытаюсь создать общий вид сетки в приложении ASP.NET MVC.

Позвольте мне объяснить с помощью некоторого кода:

public interface ITrustGrid<T>
{
    IPagedList<T> Elements { get; set; }
    IList<IColumn<T>> Columns { get; set; }
    IList<string> Headers { get; }
}

Это интерфейс класса, который позволяет мне устанавливать столбцы и выражения в моем контроллере.

Я передаю реализации частичному представлению, как это:

<% Html.RenderPartial("SimpleTrustGridViewer", ViewData["employeeGrid"] as TrustGrid<EmployeeInfoDTO>); %>

Проблема в том, что я не могу понять, как сделать частичное представление, которое делает сетку общей.

Другими словами, я хочу включить это:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ITrustGrid<EmployeeInfoDTO>>" %>

примерно так:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ITrustGrid<T>>" %>

=> Как сделать мой частичный вид наиболее простым?

EDIT:

Я решил эту проблему, используя TrustGridBuilder с открытым методом GetGrustGrid () TrustGrid, который возвращает неуниверсальный TrustGrid. TrustGrid содержит строки вместо linq. Поэтому я выполняю linq в методе GetTrustGrid () и помещаю строки в объект TrustGrid.

Спасибо всем, кто помог мне на правильном пути.

Ответы [ 4 ]

7 голосов
/ 17 мая 2009

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

Пример:

public interface IDisplayModel
{
    string DisplayText{get;set;}
    string ImageUrl{get;set;}
    string AltText{get;set;}
}

public interface ITrustGrid<T> where T : IDisplayModel
{    
    IPagedList<T> Elements { get; set; }    
    IList<IColumn<T>> Columns { get; set; }    
    IList<string> Headers { get; }
}

<%@ Control Language="C#" 
    Inherits="System.Web.Mvc.ViewUserControl<ITrustGrid<IDisplayModel>>" %>

Естественно, ваш IDisplayModel будет зависеть от вашего желаемого поведения. Это позволит вам затем передать что-нибудь в этот партиал, который реализует этот базовый интерфейс, чтобы установить общее поведение.

5 голосов
/ 17 мая 2009

Это невозможно сделать так. Причина в том, что .aspx сгенерирует класс, над которым у вас мало контроля, и вы не можете добавить к нему универсальный параметр. Я думаю, что самый простой способ - передать его как object.

1 голос
/ 17 мая 2009

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

Например, я бы использовал класс данных неуниверсального представления с дополнительным полем:

public interface ITrustGrid {
    IPagedList Elements { get; set; }
    IList<IColumn> Columns { get; set; }
    IList<string> Headers { get; }

    Func<object, string> ElementRenderer { get; }
}

В вашем основном виде вы подготовите данные вида:

<%
ITrustGrid data = (ITrustGrid)ViewData["employeeGrid"];
data.ElementRenderer = new Func<object, string>(delegate(o) {
    var employee = (Employee)o;
    //render employee
    return html;
});

Html.RenderPartial("SimpleTrustGridViewer", data);
%>

Находясь в вашей части сетки, вы будете обрабатывать сетку как обычно, а затем вызывать делегат для визуализации каждой отдельной ячейки:

<%
foreach(var element in ViewData.Elements){
    %>
    <tr>
        <td><%=ViewData.ElementRenderer(element) %></td>
    </tr>
    <%
}
%>

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

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

0 голосов
/ 17 мая 2009

@ Lck:

Я делаю что-то подобное в моем контроллере:

var columns = new List<IColumn<EmployeeInfoDTO>>
                  {
                      new Column<EmployeeInfoDTO>("Full name", e => string.Format("{0} {1}", e.FirstName, e.Name)),
                      new Column<EmployeeInfoDTO>("Examination date", e => e.ExaminationDate.HasValue? string.Format("{0} days ago", currentDate.Subtract(e.ExaminationDate.Value).Days) : "Unknown")
                  };

var employeeGrid = new TrustGrid<EmployeeInfoDTO> { Columns = columns, Elements = GetEmployees(currentPageIndex)};

ViewData["employeeGrid"] = employeeGrid;

Итак, с моей частичной точки зрения, я могу сделать это:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ITrustGrid<EmployeeInfoDTO>>" %>
<table>
    <thead>
        <tr>
            <%
                foreach (string header in Model.Headers)
                    Response.Write(Html.Th(header));
            %>
        </tr>
    </thead>
    <tbody>
        <%
            foreach (var element in Model.Elements)
            {
                Response.Write("<tr>");
                foreach (var column in Model.Columns)
                    Response.Write(Html.Td(column.ValueExpression(element)));
                Response.Write("</tr>");
            }
        %>
    </tbody>
</table>
<div class="pager">
    <%= Html.Pager(Model.Elements.PageSize, Model.Elements.PageNumber, Model.Elements.TotalItemCount)%>
</div>

Как видите, ни один из кодов в моей части не зависит от используемого типа. Поэтому я все еще думаю, что есть простое решение.

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