2009-05-10 42 views
17

Tengo un control WPF ListView con un GridView. Me gustaría cambiar el tamaño de las columnas GridView cuando cambia el contenido de las columnas.Tamaño de la fuerza de columnas GridView dentro de ListView

Tengo varios conjuntos de datos distintos, pero cuando cambio de uno a otro, el tamaño de cada columna se ajusta a los datos anteriores. Me gustaría actualizar dinámicamente ¿Cómo puedo hacer eso?

+2

Tengo el mismo problema. Cambie la fuente de datos y el ancho de las columnas no cambie de tamaño. Me encantaría configurar la fuente y llamar a un método AutoSizeColumns o similar. –

+0

+1, ¡esto me está volviendo loco! – Oskar

Respuesta

-1

se pudiera medir la cadena más larga en píxeles y luego ajustar los anchos de columna en consecuencia:

Graphics graphics = this.CreateGraphics(); 
SizeF textSize = graphics.MeasureString("How long am I?", this.Font); 

Si crea un algoritmo para determinar el tamaño de cada columna como una relación de estas longitudes, usted debe conseguir un buen resultado.

+0

Bueno, supongo que esto no funcionará con WPF y vinculante ... –

29

Finalmente, algunos resultados en este caso. He encontrado una manera de hacer el mismo auto-tamaño que se hace inicialmente y cuando se hace doble clic en la pinza en el encabezado de una columna.

public void AutoSizeColumns() 
{ 
    GridView gv = listView1.View as GridView; 
    if (gv != null) 
    { 
     foreach (var c in gv.Columns) 
     { 
      // Code below was found in GridViewColumnHeader.OnGripperDoubleClicked() event handler (using Reflector) 
      // i.e. it is the same code that is executed when the gripper is double clicked 
      if (double.IsNaN(c.Width)) 
      { 
       c.Width = c.ActualWidth; 
      } 
      c.Width = double.NaN; 
     } 
    } 
} 
+0

Gran solución. Gracias. –

1

¿No hay una manera de enlazar con el ActualWidth de la columna? Algo así como:

<GridViewColumn x:Name="column1" Width="{Binding ElementName=column1, Path=ActualWidth}" /> 

he probado esto y funciona sólo la primera vez, parece. Sin error vinculante

+0

También he intentado: Ancho = "{Ruta de enlace = Actual Ancho, RelativeSource = {x: Static RelativeSource.Self}}" – Thia

+0

Sí, copia ActualWidth sobre Ancho, que es el ancho deseado para siempre. El auto-tamaño está desactivado por primera vez. ActualWidth nunca cambia de nuevo, por lo que el ancho previsto tampoco lo hará. – ygoe

4

Sobre la base de la respuesta de Oskars, este es un comportamiento de mezcla para ajustar automáticamente el tamaño de las columnas cuando cambia el contenido.

/// <summary> 
/// A <see cref="Behavior{T}"/> implementation which will automatically resize the automatic columns of a <see cref="ListView">ListViews</see> <see cref="GridView"/> to the new content. 
/// </summary> 
public class GridViewColumnResizeBehaviour : Behavior<ListView> 
{ 
     /// <summary> 
     /// Listens for when the <see cref="ItemsControl.Items"/> collection changes. 
     /// </summary> 
     protected override void OnAttached() 
     { 
      base.OnAttached(); 

      var listView = AssociatedObject; 
      if (listView == null) 
       return; 

      AddHandler(listView.Items); 
     } 

     private void AddHandler(INotifyCollectionChanged sourceCollection) 
     { 
      Contract.Requires(sourceCollection != null); 

      sourceCollection.CollectionChanged += OnListViewItemsCollectionChanged; 
     } 

     private void RemoveHandler(INotifyCollectionChanged sourceCollection) 
     { 
      Contract.Requires(sourceCollection != null); 

      sourceCollection.CollectionChanged -= OnListViewItemsCollectionChanged; 
     } 

     private void OnListViewItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs) 
     { 
      var listView = AssociatedObject; 
      if (listView == null) 
       return; 

      var gridView = listView.View as GridView; 
      if (gridView == null) 
       return; 

      // If the column is automatically sized, change the column width to re-apply automatic width 
      foreach (var column in gridView.Columns.Where(column => Double.IsNaN(column.Width))) 
      { 
       Contract.Assume(column != null); 
       column.Width = column.ActualWidth; 
       column.Width = Double.NaN; 
      } 
     } 

     /// <summary> 
     /// Stops listening for when the <see cref="ItemsControl.Items"/> collection changes. 
     /// </summary> 
     protected override void OnDetaching() 
     { 
      var listView = AssociatedObject; 
      if (listView != null) 
       RemoveHandler(listView.Items); 

      base.OnDetaching(); 
     } 
} 
+0

Este comportamiento no tiene en cuenta que puede tardar un tiempo hasta que se calcule el nuevo 'ActualWidth'. Por lo tanto, podría suceder que 'ActualWidth' aún sea demasiado pequeño para ajustarse a los contenidos. – Danielku15

+0

@ Danielku15 ¿Está descubriendo que está sucediendo? Una pequeña muestra sería genial, así que puedo trabajar para solucionar este problema. – Lukazoid

+1

Tengo un ListView vinculado a un ObservableCollection. Tengo un control en mi CellTemplate de 40x40pt. Attaching the Behavior ejecuta el método OnListViewItemsCollectionChanged, pero el Ancho real es demasiado pequeño (25 puntos en mi caso). El resultado: está recortado. Parece que el proceso de diseño no se ejecutó cuando se ejecuta el controlador. – Danielku15

1

Si como yo, eres viejo y VB.NET prefiere entonces aquí es el código Oskars:

Public Sub AutoSizeColumns() 
    Dim gv As GridView = TryCast(Me.listview1.View, GridView) 
    If gv IsNot Nothing Then 
     For Each c As GridViewColumn In gv.Columns 
      If Double.IsNaN(c.Width) Then 
       c.Width = c.ActualWidth 
      End If 
      c.Width = Double.NaN 
     Next 
    End If 
End Sub 

Esto funciona muy bien en WPF, por fin alguien lo ha descubierto. Gracias, Oskar.

Cuestiones relacionadas