Pregunta ¿Cómo autoejecutar y alinear correctamente los datos de GridViewColumn en WPF?


Cómo puedo:

  • alinear a la derecha el texto en la columna ID
  • hacer que cada una de las columnas tenga el tamaño automático de acuerdo con la longitud del texto de la celda con los datos visibles más largos?

Aquí está el código:

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

respuesta parcial:

Gracias a Kjetil, la GridViewColumn.CellTemplate funciona bien y el Auto Ancho funciona, por supuesto, pero cuando la "Colección" de ObservativeCollection se actualiza con datos más largos que el ancho de columna, los tamaños de columna no se actualizan, por lo que es solo una solución para el visualización inicial de datos:

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

73
2018-02-18 10:52


origen


Respuestas:


Para hacer que cada una de las columnas se autosize, puede establecer Ancho = "Automático" en la GridViewColumn.

Para alinear a la derecha el texto en la columna ID, puede crear una plantilla de celda usando un TextBlock y establecer TextAlignment. Luego configure ListViewItem.HorizontalContentAlignment (usando un estilo con un setter en ListViewItem) para hacer que la plantilla de celda llene toda la GridViewCell.

Tal vez hay una solución más simple, pero esto debería funcionar.

Nota: la solución requiere ambos HorizontalContentAlignment = Stretch en Window.Resources y TextAlignment = Derecho en CellTemplate.

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

91
2018-02-18 11:23



Si el ancho del contenido cambia, deberá usar este código para actualizar cada columna:

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

    column.Width = double.NaN;
}

Tendría que dispararlo cada vez que se actualicen los datos de esa columna.


33
2017-12-19 00:14



Si su vista de lista también está cambiando de tamaño, puede usar un patrón de comportamiento para cambiar el tamaño de las columnas para que se ajusten al ancho completo de ListView. Casi lo mismo que usa las definiciones 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>

Vea el siguiente enlace para algunos ejemplos y enlace al código fuente http://lazycowprojects.tumblr.com/post/7063214400/wpf-c-listview-column-width-auto


17
2018-06-30 02:36



Creé la siguiente clase y la utilicé en la aplicación donde fuera necesario en lugar 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);
    }
}

9
2018-04-01 14:13



Como tenía un ItemContainerStyle, tuve que poner HorizontalContentAlignment en 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" /> 
    ....

7
2017-08-01 16:03



Me gustó la solución de user1333423, excepto que siempre cambia el tamaño de cada columna; Necesitaba permitir que algunas columnas fueran de ancho fijo. Por lo tanto, en esta versión, las columnas con un ancho establecido en "Automático" serán de tamaño automático y las configuradas en una cantidad fija no se dimensionarán automáticamente.

public class AutoSizedGridView : GridView
{
    HashSet<int> _autoWidthColumns;

    protected override void PrepareItem(ListViewItem item)
    {
        if (_autoWidthColumns == null)
        {
            _autoWidthColumns = new HashSet<int>();

            foreach (var column in Columns)
            {
                if(double.IsNaN(column.Width))
                    _autoWidthColumns.Add(column.GetHashCode());
            }                
        }

        foreach (GridViewColumn column in Columns)
        {
            if (_autoWidthColumns.Contains(column.GetHashCode()))
            {
                if (double.IsNaN(column.Width))
                    column.Width = column.ActualWidth;

                column.Width = double.NaN;                    
            }          
        }

        base.PrepareItem(item);
    }        
}

4
2018-05-15 07:32



Sé que esto es demasiado tarde, pero este es mi enfoque:

<GridViewColumn x:Name="GridHeaderLocalSize"  Width="100">      
<GridViewColumn.Header>
    <GridViewColumnHeader HorizontalContentAlignment="Right">
        <Grid Width="Auto" HorizontalAlignment="Right">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="100"/>
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Column="0" Text="Local size" TextAlignment="Right" Padding="0,0,5,0"/>
        </Grid>
    </GridViewColumnHeader>
</GridViewColumn.Header>
<GridViewColumn.CellTemplate>
    <DataTemplate>
        <TextBlock Width="{Binding ElementName=GridHeaderLocalSize, Path=Width, FallbackValue=100}"  HorizontalAlignment="Right" TextAlignment="Right" Padding="0,0,5,0" Text="Text" >
        </TextBlock>
    </DataTemplate>
</GridViewColumn.CellTemplate>

La idea principal es vincular el ancho del elemento cellTemplete con el ancho de ViewGridColumn. Ancho = 100 es el ancho predeterminado utilizado hasta el primer cambio de tamaño. No hay ningún código detrás. Todo está en xaml.


2
2018-05-25 07:39



Tuve problemas con la respuesta aceptada (porque me olvidé de la porción HorizontalAlignment = Stretch y ajusté la respuesta original).

Esta es otra técnica. Utiliza una cuadrícula con un SharedSizeGroup.

Nota: el Grid.IsSharedScope = true en el ListView.

<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">
<Grid>
    <ListView Name="lstCustomers" ItemsSource="{Binding Path=Collection}" Grid.IsSharedSizeScope="True">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="ID" Width="40">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                             <Grid>
                                  <Grid.ColumnDefinitions>
                                       <ColumnDefinition Width="Auto" SharedSizeGroup="IdColumn"/>
                                  </Grid.ColumnDefinitions>
                                  <TextBlock HorizontalAlignment="Right" Text={Binding Path=Id}"/>
                             </Grid>
                        </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>

1
2017-12-24 17:13