Asp.net mvc 3 сортировка webgrid остается? sortdir = ASC

Я немного экспериментирую с несколькими сетками в asp.net mvc. У Microsoft есть сетка, которая слишком известна в предварительном выпуске mvc 3, поэтому я подумал, что попробую это сделать.

Базовая функциональность довольно проста в реализации, но когда дело доходит до сортировки, у меня возникают некоторые проблемы. Сетка обрабатывает его сортировку по URL-адресу. В URL-адресе у вас есть столбец сортировки и направление сортировки следующим образом:? Sortdir = ASC & сорт = абонемент

Теперь вы ожидаете, что после того, как вы выполнили сортировку по определенному столбцу, сортировка сортировки по этому столбцу изменится на? sortdir = DESC но это не так. Он остается? Sortdir = ASC. Кто-нибудь знает, если это ошибка или функция, и как это решить?

Еще одна очень неприятная вещь: если я нажму на ссылку сортировки, будет выполнен запрос на httpget. Из-за этого я теряю свою модель. Поскольку на странице есть возможность фильтровать сетку (функции поиска), я хочу сохранить это в модели. По-моему, было бы намного проще и чище решить поставить эти данные в состояние модели, чем хранить его в состоянии сеанса. Возможно ли изменить поведение ссылок заголовка сортировки, чтобы выполнить пост http?

Любые идеи или мысли по этому поводу? Tnx для справки.

greetz, Koen

Код представления следующий:

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

<table>
    <tr>
        <td>
            <h1 class="normal">List of subscription</h1>
        </td>
        <td>

        </td>
    </tr>
</table>
<% using (Html.BeginForm("List", "Subscription", FormMethod.Post)) { %>

<table border="0" cellpadding="0" cellspacing="5">
    <tr>
        <td>
            Search By
        </td>
        <td>
            <%: Html.DropDownListFor(m => m.SearchByColumn, Ogone.FrontEnd.Web.Controllers.SubscriptionController.SubscriptionSearchList) %>
        </td>
        <td>
            <%: Html.TextBoxFor(m => m.SearchByText) %>
        </td>
        <td>
            <input name="button" type="submit" value="Search" />
        </td>
    </tr>
</table>

<div>
<%  
var grid = new System.Web.Helpers.WebGrid(Model.SubscriptionList,  
              columnNames: new List<string>(){"Title"},  
              canPage:false);  
 %> 
<%= grid.GetHtml(columns: grid.Columns(
             grid.Column(format: (item) => Html.ActionLink("Edit", "Edit", new { id = item.ID })),
             grid.Column("ID"),
             grid.Column("ISP"),
             grid.Column("ABONNEMENT"),
             grid.Column("MODE"),
             grid.Column("SETUPFEE"),
             grid.Column("MONTHLYFEE"))
             ) %>
</div>

Ответ 1

Это происходит потому, что имена столбцов сетки должны соответствовать вашим полям или свойствам. Метод, который генерирует url в заголовке сетки, сравнивает "sort" с строкой запроса url с ограниченными столбцами и с именем столбца таблицы. Три из них должны быть одинаковыми. Если определение имени столбца не настроено должным образом, URL-адрес не будет сгенерирован правильно.

В любом случае.. вот несколько примеров правильно определенных имен столбцов.

Здесь у нас есть пример класса домена для отображения

public class Person
{
    public string FirstName;
    public string LastName;
    public Address LivesIn;
}

public class Address
{
    public string Country;
    public string City;
}

Теперь можно отобразить Список

Используйте имена столбцов в качестве полей

grid.Column("FirstName"),
grid.Column("LastName"),
grid.Column("LivesIn.City"),
grid.Column("LivesIn.Country")

... все столбцы имеют правильный URL-адрес сортировки

Если вы создадите опечатку в имени столбца, вы получили исключение

grid.Column("FirstName"),
grid.Column("MyLastName"), <-- this throws exception
grid.Column("LivesIn.City"),
grid.Column("LivesIn.Country")

Но вы можете использовать формат и не будет никаких исключений

grid.Column("FirstName"),
grid.Column("MyLastName", format: item => item.LastName</text>),
grid.Column("LivesIn.City"),
grid.Column("LivesIn.Country")

... но сортировка url для столбца MyLastName будет ПЛОХО!!! все время sortDir = ASC

Вам нужно использовать хорошее имя столбца для правильного сортировки url и пользовательского формата, поэтому...

grid.Column("FirstName"),
grid.Column("LastName", format: item => item.LastName),
grid.Column("LivesIn.City"),
grid.Column("LivesIn.Country")

... все нормально

Как насчет сложного типа?

grid.Column("FirstName"),
grid.Column("LastName"),
grid.Column("LivesIn.MyNonExistingField", format: item => item.LivesIn.City),
grid.Column("LivesIn.Country")

.... ничего себе... все в порядке.. этот парень с ошибкой.. столбец "LivesIn.MyNonExistingField" имеет правильный URL-адрес сортировки.

Хорошо... Что делать, если мы не хотим раскрывать нашу структуру домена. Затем нам нужно добавить список имен столбцов во время привязки

var grid = new WebGrid(persons, columnNames: new [] { "Foo" });
-- or --
grid.Bind(persons, columnNames: new [] { "Foo" });

grid.Column("Foo", format: item => item.FirstName),
grid.Column("LastName"),
grid.Column("LivesIn.MyNonExistingField", format: item => item.LivesIn.City),
grid.Column("LivesIn.Country")

.. теперь столбец Foo имеет правильный сортировочный url

Но осторожно!!! Есть еще одна ошибка.

Если мы добавим имена ручных столбцов в привязку, то все столбцы будут пропущены до тех пор, пока не будет найден столбец вручную. Пример:

var grid = new WebGrid(persons, columnNames: new [] { "Foo" });
-- or --
grid.Bind(persons, columnNames: new [] { "Foo" });

grid.Column("FirstName"),
grid.Column("Foo", format: item => item.LastName),
grid.Column("LivesIn.MyNonExistingField", format: item => item.LivesIn.City),
grid.Column("LivesIn.Country")

... сортировка url для столбца "FirstName" не будет сгенерирована правильно... sortDir = ASC все время... чтобы исправить это, добавьте также "FirstName" в качестве имени столбца, например:

var grid = new WebGrid(persons, columnNames: new [] { "FirstName", "Foo" });
-- or --
grid.Bind(persons, columnNames: new [] { "FirstName", "Foo" });

grid.Column("FirstName"),
grid.Column("Foo", format: item => item.LastName),
grid.Column("LivesIn.MyNonExistingField", format: item => item.LivesIn.City),
grid.Column("LivesIn.Country")

@Kohen

Удалить имена столбцов в вашем коде здесь

var grid = new System.Web.Helpers.WebGrid(Model.SubscriptionList,  
          columnNames: new List<string>(){"Title"},  
          canPage:false);

... или добавьте туда все имена столбцов, такие как "ID", "ISP" и т.д.

Ответ 2

Я думал об обходном пути проблемы, и я нашел ее.

Я добавляю дополнительный параметр в коллекцию запросов. Таким образом, я могу поместить фильтр поиска в строку запроса.

Обычно коллекция запросов выполняется только для чтения, но я нашел код, чтобы исправить это.

Код для добавления параметра к querystring:

            public static void Add(string name, string value)
            {
                    NameValueCollection qs = System.Web.HttpContext.Current.Request.QueryString;
                    qs = (NameValueCollection)System.Web.HttpContext.Current.Request.GetType().GetField("_queryString", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(System.Web.HttpContext.Current.Request);
                    PropertyInfo readOnlyInfo = qs.GetType().GetProperty("IsReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
                    readOnlyInfo.SetValue(qs, false, null);
                    qs[name] = value;
                    readOnlyInfo.SetValue(qs, true, null);
            }

Новый код контроллера:

            public ActionResult Index(string SearchFilter)
            {
                    // check querystring search
                    if (string.IsNullOrEmpty(SearchFilter) && !String.IsNullOrEmpty(Request.QueryString["search"]))
                            SearchFilter = Request.QueryString["search"];

                    var model = new Models.SubscriptionListModel { SearchFilter = SearchFilter };

                    if (string.IsNullOrEmpty(SearchFilter))
                    {
                            model.SubscriptionList = _subscriptionHandler.ReadWhereIdLessThanThousand();
                    }
                    else
                    {
                            // add search filter to the querystring
                            Common.QueryString.Add("search", SearchFilter);
                            model.SubscriptionList = _subscriptionHandler.ReadWhereContains(SearchFilter);
                    }

                    if (Request.IsAjaxRequest())
                    {
                            return View("SubscriptionList", model);
                    }
                    else
                    {
                            return View("Index", model);
                    }
            }

Если у кого-то есть более чистое решение, чтобы исправить это, предложения по-прежнему приветствуются: -)

Ответ 3

Я не уверен, почему DESC не переключается на ASC. У меня есть аналогичный пример, и он работает отлично. Используйте контейнер ajax (ajaxUpdateContainerId). Это могло бы помочь, если бы ничто другое не решило проблему, с которой вы столкнулись с запросом httpget, сохраняя результат поиска. Вот то, что у меня есть: (я использую бритву, но должен быть достаточно легким для преобразования).

Просто добавьте новое свойство: ajaxUpdateContainerId: " div_name"

Оберните сетку с помощью div с идентификатором div_name

@{
var grid = new System.Web.Helpers.WebGrid(Model.SubscriptionList, canPage:false, ajaxUpdateContainerId: "grid");  
}
<div id="grid">
    @grid.GetHtml(columns: grid.Columns(  
    grid.Column(format:(item) => Html.ActionLink("Edit", "Edit", new { id=item.Id })),
    grid.Column("ISP"),
    grid.Column("ABONNEMENT"))) 
</div>

Удачи, надеюсь, что это поможет!

Ответ 4

Я исправил эту проблему в MVC 4, установив опцию SortColumn. от сетки до значения "sort" Параметр запроса:

grid = new WebGrid(...
grid.Bind(Model...

grid.SortColumn = this.Request.QueryString["sort"];

@grid.GetHtml(columns:...

Я заметил, что для столбцов "Дата" в моей модели "SortColumn" prop. было задано имя столбца сортировки по умолчанию, независимо от значения параметра "sort" Query String...