web-dev-qa-db-fra.com

Comment faire en sorte que la dernière colonne de la grille de données WPF occupe toujours tout l'espace de gauche?

Standard WPF 4 Datagrid.

Disons que j'ai une grille de données de 200 pixels de large et 2 colonnes. J'aimerais que les colonnes occupent toujours tout l'espace, ce qui signifie que si l'utilisateur redimensionne la première colonne à 50 pixels, la dernière sera de 150.

Au départ, je définissais une largeur de 100 pixels pour la 1ère colonne et * pour la dernière (en XAML).

Je pensais que le problème venait de la suppression de la 3ème colonne virtuelle, comme expliqué ici:

http://wpf.codeplex.com/Thread/View.aspx?ThreadId=58939

mais il n’ya pas vraiment de différence - quand on redimensionne les colonnes, j’obtiens un espace supplémentaire à droite - avec colonne virtuelle, c’est une colonne virtuelle (couleur blanche par défaut), sans elle, c’est un espace vide (gris). défaut).

QUESTION: comment appliquer la contrainte, que l'utilisateur redimensionne les colonnes,

sum(columns width)==datagrid width

?

Édite

Oui, j'utilise WPF 4.

SOLUTION DE CONTOURNEMENT

J'ai marqué l'une des réponses comme solution, mais en réalité ce n'est pas une solution en raison de la conception de WPF. C’est tout simplement ce que WPF peut faire au mieux, et ce n’est pas très bon. Tout d’abord, l’option CanUserResize pour column signifie vraiment IsResizeable et cette option, lorsqu'elle est activée, contredit la largeur définie par *. Donc, sans quelque astuce vraiment intelligente, vous vous retrouvez avec:

  • grille de données dont la dernière colonne est redimensionnable de manière superficielle mais en fait, ce n'est pas le cas, et peu d'espace à droite est affiché (c'est-à-dire que la colonne virtuelle n'est pas redimensionnable) - pour la dernière colonne: CanUserResize = true, Width = *

  • datagrid dont la dernière colonne ne peut pas être redimensionnée par l'utilisateur et qui apparaît en conséquence, initialement aucun espace n'est affiché à droite, mais il peut être affiché lorsque l'utilisateur redimensionne un élément de datagrid - pour la dernière colonne: CanUserResize = false, Width = *

Jusqu'à présent, je peux voir deux problèmes avec la grille de données WPF:

  • dénomination trompeuse
  • contradiction de caractéristiques

Je suis encore tout à fait à l'écoute de la façon dont vraiment résoudre ce problème.

27
greenoldman

Définissez la largeur de la grille de données sur "Auto". Vous permettez aux colonnes de se redimensionner correctement dans la grille, mais vous avez câblé la largeur à 200.

UPDATE: Basée sur le commentaire de @ micas, j'ai peut-être mal interprété. Si c'est le cas, essayez d'utiliser 100 pour la largeur de la colonne de gauche et 100 * pour la colonne de droite (notez l'astérisque). La largeur par défaut de la colonne de droite sera par défaut égale à 100, mais vous pourrez la redimensionner pour remplir la grille.

21
Babak Naffas

Vous pouvez définir une largeur de colonne en étoile sur le code. Dans votre constructeur, ajoutez:

    Loaded += (s, e) => dataGrid1.Columns[3].Width =
new DataGridLength(1, DataGridLengthUnitType.Star);
5
biju

Je viens de mettre en œuvre cela comme un comportement attaché. Le problème est que lorsque vous définissez la dernière colonne de DataGrid sur *, la taille est ajustée, mais tout l'ajustement automatique des autres cellules est gâché. Pour résoudre ce problème, le comportement associé effectue un ajustement manuel manuel des autres cellules (non dernières). 

Cela fonctionne également lors du redimensionnement des autres colonnes - une fois chargé, vous pouvez le redimensionner et la dernière colonne sera toujours remplie. Notez que ce comportement fonctionne une fois sur l'événement Loaded

// Behavior usage: <DataGrid DataGridExtensions.LastColumnFill="True"/>
public class DataGridExtensions
{
    public static readonly DependencyProperty LastColumnFillProperty = DependencyProperty.RegisterAttached("LastColumnFill", typeof(bool), typeof(DataGridExtensions), new PropertyMetadata(default(bool), OnLastColumnFillChanged));

    public static void SetLastColumnFill(DataGrid element, bool value)
    {
        element.SetValue(LastColumnFillProperty, value);
    }

    public static bool GetLastColumnFill(DataGrid element)
    {
        return (bool)element.GetValue(LastColumnFillProperty);
    }

    private static void OnLastColumnFillChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var dataGrid = d as DataGrid;
        if (dataGrid == null) return;

        dataGrid.Loaded -= OnDataGridLoaded;
        dataGrid.Loaded += OnDataGridLoaded;
    }        

    private static void OnDataGridLoaded(object sender, RoutedEventArgs e)
    {
        var dataGrid = sender as DataGrid;
        if (dataGrid == null) return;

        var lastColumn = dataGrid.Columns.LastOrDefault();
        if(lastColumn != null)
            lastColumn.Width = new DataGridLength(1, DataGridLengthUnitType.Star);

        // Autofit all other columns
        foreach (var column in dataGrid.Columns)
        {
            if (column == lastColumn) break;

            double beforeWidth = column.ActualWidth;
            column.Width = new DataGridLength(1, DataGridLengthUnitType.SizeToCells);
            double sizeCellsWidth = column.ActualWidth;
            column.Width = new DataGridLength(1, DataGridLengthUnitType.SizeToHeader);
            double sizeHeaderWidth = column.ActualWidth;
            column.MinWidth = Math.Max(beforeWidth, Math.Max(sizeCellsWidth, sizeHeaderWidth));
        }
    }
}
4
Dr. ABT

Soyez prévenu: c'est un hack ....

Je me suis inscrit à l'événement "AutoGeneratedColumns" dans la méthode "OnLastColumnFillChanged" de la classe de Dr. ABT et y ai copié la méthode Loaded, et cela fonctionne. Je ne l'ai pas encore complètement testé, donc YMMV.

Mon changement:

    private static void OnLastColumnFillChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var dataGrid = d as DataGrid;
        if (dataGrid == null) return;

        dataGrid.Loaded -= OnDataGridLoaded;
        dataGrid.Loaded += OnDataGridLoaded;

        dataGrid.AutoGeneratedColumns -= OnDataGrid_AutoGeneratedColumns;
        dataGrid.AutoGeneratedColumns += OnDataGrid_AutoGeneratedColumns;
    }

    private static void OnDataGrid_AutoGeneratedColumns(object sender, EventArgs e)
    {
        var dataGrid = sender as DataGrid;
        if (dataGrid == null) return;

        var lastColumn = dataGrid.Columns.LastOrDefault();
        if (lastColumn != null)
            lastColumn.Width = new DataGridLength(1, DataGridLengthUnitType.Star);

        // Autofit all other columns
        foreach (var column in dataGrid.Columns)
        {
            if (column == lastColumn) break;

            double beforeWidth = column.ActualWidth;
            column.Width = new DataGridLength(1, DataGridLengthUnitType.SizeToCells);
            double sizeCellsWidth = column.ActualWidth;
            column.Width = new DataGridLength(1, DataGridLengthUnitType.SizeToHeader);
            double sizeHeaderWidth = column.ActualWidth;
            column.MinWidth = Math.Max(beforeWidth, Math.Max(sizeCellsWidth, sizeHeaderWidth));
        }
    }

Oh, et n'oubliez pas d'ajouter l'espace de noms à la déclaration XAML! :)

Là-haut:

xmlns:ext="clr-namespace:TestProject.Extensions"

Et puis dans la déclaration DataGrid:

ext:DataGridExtensions.LastColumnFill="True"

Mise à jour : J'ai dit que le kilométrage varierait! Le mien l'a certainement fait.

Ce bit entier de "colonnes d'ajustement automatique" a fait en sorte que certaines de mes colonnes dans un DataGrid avec un nombre variable de colonnes ne soient aussi larges que l'en-tête de colonne. J'ai supprimé cette partie et elle semble maintenant fonctionner sur tous les DataGrids de l'application.

Maintenant j'ai:

    private static void OnDataGrid_AutoGeneratedColumns(object sender, EventArgs e)
    {
        var dataGrid = sender as DataGrid;
        if (dataGrid == null) return;

        UpdateColumnWidths(dataGrid);

    }

    private static void OnDataGridLoaded(object sender, RoutedEventArgs e)
    {
        var dataGrid = sender as DataGrid;
        if (dataGrid == null) return;

        UpdateColumnWidths(dataGrid);
    }

    private static void UpdateColumnWidths(DataGrid dataGrid)
    {
        var lastColumn = dataGrid.Columns.LastOrDefault();
        if (lastColumn == null) return;

        lastColumn.Width = new DataGridLength(1.0d, DataGridLengthUnitType.Star);

    }
0
pennyrave