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...