90 votes

Comment redimensionner et aligner à droite les données d'une GridViewColumn dans WPF ?

Comment puis-je :

  • aligner à droite le texte de la colonne ID
  • faire en sorte que chacune des colonnes s'auto-dimensionne en fonction de la longueur du texte de la cellule dont les données visibles sont les plus longues ?

Voici le code :

<ListView Name="lstCustomers" ItemsSource="{Binding Path=Collection}">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="ID" DisplayMemberBinding="{Binding Id}" Width="40"/>
            <GridViewColumn Header="First Name" DisplayMemberBinding="{Binding FirstName}" Width="100" />
            <GridViewColumn Header="Last Name" DisplayMemberBinding="{Binding LastName}"/>
        </GridView>
    </ListView.View>
</ListView>

réponse partielle :

Merci Kjetil, le GridViewColumn.CellTemplate fonctionne bien et la largeur automatique fonctionne bien sûr, mais lorsque l'ObservativeCollection "Collection" est mis à jour avec des données plus longues que la largeur de la colonne, les tailles des colonnes ne se mettent pas à jour elles-mêmes, donc c'est seulement une solution pour l'affichage initial des données :

<ListView Name="lstCustomers" ItemsSource="{Binding Path=Collection}">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="ID" Width="Auto">
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Id}" TextAlignment="Right" Width="40"/>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
            <GridViewColumn Header="First Name" DisplayMemberBinding="{Binding FirstName}" Width="Auto" />
            <GridViewColumn Header="Last Name" DisplayMemberBinding="{Binding LastName}" Width="Auto"/>
        </GridView>
    </ListView.View>
</ListView>

2 votes

Avez-vous trouvé une solution à votre problème de taille automatique ? Je rencontre le même problème.

2 votes

@Oskar - la virtualisation de la liste empêche une auto-solution. La liste ne connaît que les éléments actuellement visibles et définit la taille en conséquence. S'il y a d'autres éléments plus bas dans la liste, elle ne les connaît pas et ne peut donc pas en tenir compte. Le livre ProgrammingWPF - Sells-Griffith recommande des largeurs de colonnes manuelles si vous utilisez la liaison de données. :(

0 votes

@Gishu Merci, cela a du sens

106voto

Kjetil Watnedal Points 2917

Pour que chacune des colonnes ait une taille automatique, vous pouvez définir Width="Auto" sur la GridViewColumn.

Pour aligner à droite le texte de la colonne ID, vous pouvez créer un modèle de cellule utilisant un TextBlock et définir l'alignement du texte. Définissez ensuite le paramètre ListViewItem.HorizontalContentAlignment (en utilisant un style avec un paramètre sur le ListViewItem) pour que le modèle de cellule remplisse la totalité de la GridViewCell.

Il existe peut-être une solution plus simple, mais celle-ci devrait fonctionner.

Nota: la solution nécessite à la fois HorizontalContentAlignment=Stretch dans Window.Resources et Alignement du texte = droite dans le modèle de cellule.

<Window x:Class="WpfApplication6.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.Resources>
    <Style TargetType="ListViewItem">
        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
    </Style>
</Window.Resources>
<Grid>
    <ListView Name="lstCustomers" ItemsSource="{Binding Path=Collection}">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="ID" Width="40">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Id}" TextAlignment="Right" />
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn Header="First Name" DisplayMemberBinding="{Binding FirstName}" Width="Auto" />
                <GridViewColumn Header="Last Name" DisplayMemberBinding="{Binding LastName}" Width="Auto"/>
            </GridView>
        </ListView.View>
    </ListView>
</Grid>
</Window>

0 votes

@Kjetil - Puis-je appliquer ce paramètre à une colonne spécifique ?

15 votes

+1 pour : <Setter Property="HorizontalContentAlignment" Value="Stretch" />

0 votes

Génial, mais j'ai 15 colonnes, y a-t-il un moyen de ne pas avoir à répéter le modèle de cellule pour toutes ces colonnes ?

39voto

RandomEngy Points 6937

Si la largeur du contenu change, vous devrez utiliser ce bout de code pour mettre à jour chaque colonne :

private void ResizeGridViewColumn(GridViewColumn column)
{
    if (double.IsNaN(column.Width))
    {
        column.Width = column.ActualWidth;
    }

    column.Width = double.NaN;
}

Il faudrait le déclencher à chaque fois que les données de cette colonne sont mises à jour.

1 votes

A quoi l'attacheriez-vous ?

1 votes

Exécutez-la manuellement sur la GridViewColumn après avoir mis à jour les données de la grille. Si vous disposez d'un ViewModel, vous pouvez souscrire à l'événement PropertyChanged de celui-ci et l'exécuter ensuite.

0 votes

+1 Merci pour cela ! Cela m'a beaucoup aidé ! Pas lié à cette question, mais quand même : J'ai mis en œuvre une liste / gridView personnalisée où vous pouvez ajouter / supprimer dynamiquement des colonnes au moment de l'exécution via l'interface graphique. Cependant, lorsque j'ai supprimé et réajouté une colonne, elle n'apparaît plus. Tout d'abord, j'ai pensé qu'elle n'avait pas été ajoutée du tout (pour une raison quelconque), mais ensuite (en utilisant Snoop) j'ai découvert qu'elle est effectivement ajoutée, mais que sa largeur réelle est de 0 (elle a été redimensionnée automatiquement et évidemment réinitialisée lorsque la colonne a été supprimée). Maintenant, j'utilise votre code pour définir la largeur correcte de la colonne après l'avoir réintroduite dans les colonnes. Merci beaucoup !

18voto

Rolf Wessels Points 313

Si votre liste est également redimensionnée, vous pouvez utiliser un modèle de comportement pour redimensionner les colonnes afin qu'elles s'adaptent à la largeur totale de la liste. C'est presque la même chose que d'utiliser les définitions de grid.column.

<ListView HorizontalAlignment="Stretch"
          Behaviours:GridViewColumnResize.Enabled="True">
        <ListViewItem></ListViewItem>
        <ListView.View>
            <GridView>
                <GridViewColumn  Header="Column *"
                                   Behaviours:GridViewColumnResize.Width="*" >
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <TextBox HorizontalAlignment="Stretch" Text="Example1" />
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>

Voir le lien suivant pour quelques exemples et un lien vers le code source http://lazycowprojects.tumblr.com/post/7063214400/wpf-c-listview-column-width-auto

0 votes

Celui-ci est cool. Il résout le problème et vous donne toutes les , n , Auto fonctionnalité que vous recherchez.

0 votes

C'est ce que je cherchais. :D

0 votes

Remarque : il semble y avoir un bogue. Lorsque la ListView est redimensionnée verticalement, au point de faire apparaître une barre de défilement verticale, la colonne augmente continuellement en largeur jusqu'à ce que la barre de défilement disparaisse.

12voto

user1333423 Points 11

J'ai créé la classe suivante et je l'ai utilisée dans toute l'application à chaque fois que cela était nécessaire à la place de GridView :

/// <summary>
/// Represents a view mode that displays data items in columns for a System.Windows.Controls.ListView control with auto sized columns based on the column content     
/// </summary>
public class AutoSizedGridView : GridView
{        
    protected override void PrepareItem(ListViewItem item)
    {
        foreach (GridViewColumn column in Columns)
        {
            // Setting NaN for the column width automatically determines the required
            // width enough to hold the content completely.

            // If the width is NaN, first set it to ActualWidth temporarily.
            if (double.IsNaN(column.Width))
              column.Width = column.ActualWidth;

            // Finally, set the column with to NaN. This raises the property change
            // event and re computes the width.
            column.Width = double.NaN;              
        }            
        base.PrepareItem(item);
    }
}

7voto

Blam Points 17325

Comme j'avais un ItemContainerStyle, j'ai dû placer l'HorizontalContentAlignment dans l'ItemContainerStyle.

    <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=FieldDef.DispDetail, Mode=OneWay}" Value="False">
                         <Setter Property="Visibility" Value="Collapsed"/>
                    </DataTrigger>
                </Style.Triggers>
                <Setter Property="HorizontalContentAlignment" Value="Stretch" /> 
    ....

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X