2010-12-23 14 views
12

Estoy experimentando un poco con varias cuadrículas en asp.net mvc. Microsoft también tiene una grilla en la presentación de mvc 3, así que pensé en probarla.asp.net mvc 3 webgrid sorting remains? Sortdir = ASC

La funcionalidad básica es bastante fácil de implementar, pero cuando se trata de ordenar, tengo algunos problemas. La cuadrícula maneja su clasificación por url. En la url que tiene la columna de ordenación y la dirección de ordenación de la siguiente manera:? sortdir = ASC & tipo = ABONNEMENT

Ahora se puede esperar que después de haber realizado la clasificación en la columna determinada, la cadena de consulta sortdir en esa columna cambiaría a? sortdir = DESC pero no es así. Se queda? Sortdir = ASC. ¿Alguien sabe si esto es un error o una característica, y cómo resolver esto?

Otra cosa muy molesta: si hago clic en un enlace de ordenación, se realiza una solicitud de httpget. Debido a esto pierdo mi modelo. Debido a que existe la posibilidad en la página de filtrar la cuadrícula (funcionalidad de búsqueda), quiero preservar esto en el modelo. Sería una solución de limpieza mucho más fácil & en mi opinión para poner estos datos en el estado del modelo, que para almacenarlo en el estado de la sesión. ¿Es posible cambiar el comportamiento de los enlaces de encabezado de clasificación para que se ejecute una publicación http?

¿Alguna idea o idea al respecto? Tnx por la ayuda.

greetz, Koen

El código de la vista es el siguiente:

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

+0

Me gustaría saber si hay una forma de forzar que una red web publique en lugar de obtener para ordenar y paginar . – Grubsnik

+0

Si su tabla no es demasiado grande, ¿podría ordenar en el cliente usando jquery.tablesorter? –

Respuesta

1

No estoy seguro de por qué no se DESC switchign a ASC. Tengo un ejemplo similar y funciona bien. Utilice Ttry el contenedor ajax (ajaxUpdateContainerId). Esto podría ayudar, si nada más resolvería el problema que está teniendo con la solicitud de httpget, manteniendo el resultado de búsqueda. Esto es lo que tengo: (Estoy usando una afeitadora, pero debería ser lo suficientemente fácil de convertir).

sólo tiene que añadir la nueva propiedad: ajaxUpdateContainerId: "div_name"

Wrap la rejilla con un div que tiene un diámetro interior de 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> 

mejor de la suerte, espero que ayude!

24

Esto sucede porque los nombres de las columnas de cuadrícula deben corresponder a sus campos o propiedades. El método que genera url en el encabezado de la grilla compara "ordenar" de la cadena de consulta url con columnas limitadas y con el nombre de columna de la grilla. Los tres deben ser iguales. Si la definición del nombre de su columna no está configurada correctamente, la url no se generará correctamente.

De todos modos ... aquí hay algunos ejemplos de nombres de columna definidos correctamente.

Aquí tenemos la clase de dominio de ejemplo para mostrar

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

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

Ahora vamos a la lista de visualización

Use sus nombres de las columnas como campos

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

... todas las columnas tienen correcta clasificación url

Si comete un error ortográfico en el nombre de la columna obtiene la excepción

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

pero se puede utilizar el formato y no habrá ninguna excepción lanzada

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

... pero la clasificación para la url MyLastName columna será malo !!! todo el tiempo sortDir = ASC

Es necesario utilizar un buen nombre de la columna que contiene una URL de clasificación adecuada y formato personalizado de manera ...

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

... todo está bien

¿Qué hay de tipo complejo ?

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

.... wow ... todo está bien .. eso es niño de error .. columna "LivesIn.MyNonExistingField" tiene url clasificación adecuada.

Ok ... ¿Qué pasa si no queremos exponer nuestra estructura de dominio. Entonces tenemos que añadir la lista de nombres de columna durante la unión

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") 

.. ahora la columna Foo tiene clasificación adecuada url

Pero cuidado !!! Hay otro error.

Si agregamos los nombres de las columnas manuales al enlace, todas las columnas se omitirán hasta que se encuentre la columna manual. Ejemplo:

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") 

... clasificación de URL para la columna "Nombre" no se generará correctamente ... sortDir = ASC todo el tiempo ... para solucionar este complemento también un "Nombre" como nombre de la columna como ésta :

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

Retire columnNames en su código aquí

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

... o añadir existe una ll nombres de sus columnas como "ID", "ISP", etc.

+0

¡Guau! Gran respuesta. –

+0

Riqueza de información. Esto probablemente debería estar marcado como "correcto". discusión de grid.Bind fue relevante para mí y resolvió mi problema. –

+1

Esta es una muy buena respuesta, pero las clases de muestra están usando todos los campos. Deberá cambiarlos a propiedades para que funcionen sus ejemplos, p. cadena pública FirstName {get; establecer;} Si intenta enlazar a los campos, obtendrá un error de columna "Nombre" no existe. – kiprainey

2

He estado pensando en una solución para el problema, y ​​he encontrado uno.

Inyerto un parámetro extra en la colección querystring. De esa manera puedo poner el filtro de búsqueda en la cadena de consulta.

Normalmente, la colección querystring es de solo lectura, pero he encontrado un código para solucionarlo.

código para agregar el parámetro de cadena de consulta:

  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); 
      } 

nuevo código del controlador:

  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); 
        } 
      } 

Si alguien tiene una solución más limpia para solucionar este problema, las sugerencias son bienvenidos :-) todavía

1

Solucioné este problema en MVC 4 al configurar el elemento 'SortColumn'. de la red con el valor de parámetro "tipo" cadena de consulta .:

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

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

@grid.GetHtml(columns:... 

me di cuenta de que para las columnas 'fecha' en prop 'sortColumn' mi modelo. se configuró con el nombre de la columna de ordenación predeterminada independientemente del valor de "ordenar" Query String param ...

+0

@Leanid Minkov, su solución simple hizo que funcione para mí también. Gracias. – Tarak