2010-01-24 19 views
12

ProblemaEl uso de fijaciones para controlar el orden de columna en una cuadrícula de datos

Tengo un kit de herramientas de WPF DataGrid, y me gustaría ser capaz de cambiar entre varios órdenes de columnas predefinidas. Este es un proyecto de MVVM, por lo que los pedidos de columnas se almacenan en un ViewModel. El problema es que no puedo hacer que los enlaces funcionen para la propiedad DisplayIndex. No importa lo que intente, incluyendo el método dulce en this Josh Smith tutorial, me sale:

El DisplayIndex para la DataGridColumn con 'ID' de cabecera está fuera del intervalo. DisplayIndex debe ser mayor o igual que 0 y menor que Columns.Count. Nombre del parámetro: displayIndex. El valor real fue -1.

¿Hay alguna solución para esto?

Estoy incluyendo mi código de prueba a continuación. Por favor avíseme si ve algún problema con eso.


código de modelo de vista

public class MainViewModel 
{ 
    public List<Plan> Plans { get; set; } 
    public int IdDisplayIndex { get; set; } 
    public int NameDisplayIndex { get; set; } 
    public int DescriptionDisplayIndex { get; set; } 

    public MainViewModel() 
    { 
     Initialize(); 
    } 

    private void Initialize() 
    { 
     IdDisplayIndex = 1; 
     NameDisplayIndex = 2; 
     DescriptionDisplayIndex = 0; 
     Plans = new List<Plan> 
     { 
      new Plan { Id = 1, Name = "Primary", Description = "Likely to work." }, 
      new Plan { Id = 2, Name = "Plan B", Description = "Backup plan." }, 
      new Plan { Id = 3, Name = "Plan C", Description = "Last resort." } 
     }; 
    } 
} 

Plan de Clase

public class Plan 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
} 

código Ventana - esto utiliza Josh Smith's DataContextSpy

<Window 
    x:Class="WpfApplication1.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WpfApplication1" 
    xmlns:mwc="http://schemas.microsoft.com/wpf/2008/toolkit" 
    Title="Main Window" Height="300" Width="300"> 
    <Grid> 
     <mwc:DataGrid ItemsSource="{Binding Plans}" AutoGenerateColumns="False"> 
      <mwc:DataGrid.Resources> 
       <local:DataContextSpy x:Key="spy" /> 
      </mwc:DataGrid.Resources> 
      <mwc:DataGrid.Columns> 
       <mwc:DataGridTextColumn 
        Header="ID" 
        Binding="{Binding Id}" 
        DisplayIndex="{Binding Source={StaticResource spy}, Path=DataContext.IdDisplayIndex}" /> 
       <mwc:DataGridTextColumn 
        Header="Name" 
        Binding="{Binding Name}" 
        DisplayIndex="{Binding Source={StaticResource spy}, Path=DataContext.NameDisplayIndex}" /> 
       <mwc:DataGridTextColumn 
        Header="Description" 
        Binding="{Binding Description}" 
        DisplayIndex="{Binding Source={StaticResource spy}, Path=DataContext.DescriptionDisplayIndex}" /> 
      </mwc:DataGrid.Columns> 
     </mwc:DataGrid> 
    </Grid> 
</Window> 

Nota: Si sólo tiene que utilizar los números de civil para DisplayIndex, todo funciona bien, así que el problema es, sin duda, con las fijaciones.


actualización 5/1/2010

Estaba haciendo un poco de mantenimiento en mi proyecto, y me di cuenta de que cuando me encontré con él, el problema discuto en este puesto había regresado. Sabía que funcionó la última vez que lo ejecuté, así que eventualmente reduje el problema al hecho de que había instalado una versión más nueva de WPF Toolkit (Feb '10). Cuando volví a la versión de junio de 2009, todo volvió a funcionar bien. Por lo tanto, ahora estoy haciendo algo que debería haber hecho en primer lugar: estoy incluyendo el WPFToolkit.dll que funciona en la carpeta de mi solución y lo controlo en el control de la versión. Sin embargo, es desafortunado que el kit de herramientas más nuevo tenga un cambio radical.

Respuesta

4

(Mi respuesta anterior fue lejos de alcanzarse - por lo que se eliminan - Voy a tratar de responder de nuevo después de reproducir el error en mi máquina)

El problema se encuentra con deriva del hecho de que cuando los enlaces son evaluada por primera vez, la propiedad DataContext aún se establece en null. Esto, por alguna extraña razón, pero desconocido para mí, hace que el enlace se evalúe en -1.Sin embargo, si se asegura de configurar DataContextantes de se evalúan las consolidaciones, estará bien. Desafortunadamente, esto solo podría ser posible en código subyacente, por lo tanto, durante el tiempo de ejecución y no en el tiempo de diseño. Entonces, en tiempo de diseño, todavía no sé cómo eludir el error.

Para ello, establezca la propiedad DataContext de la ventana antes de la llamada a InitializeComponent así:

public MainWindow() 
{ 
    DataContext = new MainViewModel(); 
    InitializeComponent(); 
} 

Espero que esto ayude.

+0

Bueno, esto es interesante. Si ejecuto mi aplicación de prueba, tu solución funciona perfectamente. En mi aplicación real, el 'DataGrid' en cuestión está realmente en un' UserControl', y por alguna razón, si aplico el 'DataContextSpy' (que no intenté hasta ahora, ya que había fallado en mi aplicación de prueba) , funciona incluso si no pospongo la llamada a 'InitializeComponent()'. Creo que esto debe ser porque solo estoy configurando 'Content' en' ContentControl' en lugar de hacer 'window.Show()'. En cualquier caso, gracias por tomarse el tiempo para resolver esto por mí (+1 y √). – devuxer

12

Establezca FallbackValue=<idx> en su encuadernación DisplayIndex, donde <idx> es el índice de su columna. Por ejemplo:

DisplayIndex="{Binding Source={StaticResource spy}, Path=DataContext.IdDisplayIndex, FallbackValue=0}" /> 
+2

Funciona perfectamente, y elegante también. – ShadowChaser

+1

Este es el camino a seguir, sin duda. –

1

Estoy agregando esto como respuesta, ya que no puedo comentar todavía. La razón por la cual el valor de la DisplayIndex se establece en -1 es:

La propiedad DisplayIndex tiene un valor predeterminado de -1 antes de añadirlo a la colección DataGrid.Columns. Este valor se actualiza cuando la columna se agrega a DataGrid.

El DataGrid requiere que la propiedad DisplayIndex de cada columna debe ser un entero único de 0 al Conteo de columnas -1. Por lo tanto, cuando cambia el índice de visualización de una columna, el cambio normalmente hace que el índice de visualización de otras columnas también cambie.

Las restricciones en el valor DisplayIndex se aplican mediante un mecanismo ValidateValueCallback. Si intenta establecer un valor que es no válido, se lanza una excepción en tiempo de ejecución.

Cuando se cambia el valor de la propiedad DisplayIndex, se genera el evento DataGrid.ColumnDisplayIndexChanged.

Fuente: http://msdn.microsoft.com/en-us/library/vstudio/system.windows.controls.datagridcolumn.displayindex(v=vs.100).aspx

así que supongo que es posible comprobar este valor cuando se cambia el uso de dicho evento.

La solución mencionada por Aviad no funcionó para mí. Tengo mi Datagrid en un UserControl, lo mismo que el OP, y cambiar el orden del constructor ViewModel, la declaración DataContext y el método InitializeComponent() no ayudaron.

El método FallbackValue de Pakman funcionó muy bien, por otro lado.

Cuestiones relacionadas