it-swarm.com.ru

Как автоматически изменять размер и выравнивать данные GridViewColumn в WPF?

Как я могу:

  • выровнять текст в столбце идентификатора вправо
  • сделать каждый из столбцов автоматическим размером в соответствии с длиной текста ячейки с самыми длинными видимыми данными?

Вот код:

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

частичный ответ:

Благодаря Kjetil, GridViewColumn.CellTemplate работает хорошо, и Auto Width работает, конечно, но когда "Коллекция" ObservativeCollection обновляется данными, длина которых превышает ширину столбца, размеры столбцов не обновляются, так что это только решение для первоначальное отображение данных:

<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>
79
Edward Tanguay

Чтобы сделать каждый столбец автоматически изменяемым, вы можете установить Width = "Auto" в GridViewColumn.

Чтобы выровнять текст в столбце ID по правому краю, вы можете создать шаблон ячейки с помощью TextBlock и установить TextAlignment. Затем установите ListViewItem.Hor HorizontalContentAlignment (используя стиль с установщиком в ListViewItem), чтобы шаблон ячейки заполнил весь GridViewCell.

Может быть, есть более простое решение, но это должно работать.

Примечание: для решения требуется оба параметра HorizontalContentAlignment = Stretch в Window.Resources и TextAlignment = Right в шаблоне 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>
97
Kjetil Watnedal

Если ширина содержимого изменяется, вам придется использовать этот бит кода для обновления каждого столбца:

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

    column.Width = double.NaN;
}

Вам придется запускать его каждый раз, когда обновляются данные для этого столбца.

33
RandomEngy

Если ваш просмотр списка также изменяет размеры, вы можете использовать шаблон поведения, чтобы изменить размер столбцов, чтобы он соответствовал полной ширине ListView. Почти так же, как вы используете определения 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>

См. Следующую ссылку для некоторых примеров и ссылки на исходный код http://lazycowprojects.tumblr.com/post/7063214400/wpf-c-listview-column-width-auto

17
Rolf Wessels

Я создал следующий класс и использовал его во всем приложении вместо 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);
    }
}
10
user1333423

Так как у меня был ItemContainerStyle, я должен был поместить HorizontalContentAlignment в 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
paparazzo

Мне понравилось решение user1333423 за исключением того, что оно всегда изменяло размер каждого столбца; Мне нужно, чтобы некоторые столбцы были фиксированной ширины. Таким образом, в этой версии столбцы с шириной, установленной в "Авто", будут иметь автоматический размер, а столбцы с фиксированной суммой не будут иметь автоматический размер.

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);
    }        
}
5
jv_

Я знаю, что это слишком поздно, но вот мой подход:

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

Основная идея состоит в том, чтобы привязать ширину элемента cellTemplete к ширине ViewGridColumn. Ширина = 100 - это ширина по умолчанию, используемая до первого изменения размера. Там нет никакого кода позади. Все в xaml.

2
Azzy Elvul

У меня были проблемы с принятым ответом (потому что я пропустил часть HorizontalAlignment = Stretch и скорректировал исходный ответ).

Это еще одна техника. Он использует Grid с SharedSizeGroup.

Примечание: the Grid.IsSharedScope = true в 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
Adam Tegen

Я создал функцию для обновления заголовков столбцов GridView для списка и вызываю ее всякий раз, когда окно изменяет размеры или когда список обновляет свой макет.

public void correctColumnWidths()
{
    double remainingSpace = myList.ActualWidth;

    if (remainingSpace > 0)
    {
         for (int i = 0; i < (myList.View as GridView).Columns.Count; i++)
              if (i != 2)
                   remainingSpace -= (myList.View as GridView).Columns[i].ActualWidth;

          //Leave 15 px free for scrollbar
          remainingSpace -= 15;

          (myList.View as GridView).Columns[2].Width = remainingSpace;
    }
}
1
Andrei Rogobete

Это твой код

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

Попробуй это

<ListView Name="lstCustomers" ItemsSource="{Binding Path=Collection}">
    <ListView.View>
        <GridView>
            <GridViewColumn DisplayMemberBinding="{Binding Id}" Width="Auto">
               <GridViewColumnHeader Content="ID" Width="Auto" />
            </GridViewColumn>
            <GridViewColumn DisplayMemberBinding="{Binding FirstName}" Width="Auto">
              <GridViewColumnHeader Content="First Name" Width="Auto" />
            </GridViewColumn>
            <GridViewColumn DisplayMemberBinding="{Binding LastName}" Width="Auto">
              <GridViewColumnHeader Content="Last Name" Width="Auto" />
            </GridViewColumn
        </GridView>
    </ListView.View>
</ListView>
0
StriderWaR