WPFでGridViewColumnデータのサイズを自動化して右揃えにする方法は?


89

どうやって:

  • ID列のテキストを右揃えにします
  • 表示されるデータが最も長いセルのテキストの長さに応じて、各列のサイズを自動化しますか?

コードは次のとおりです。

<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は適切に機能し、自動幅はもちろん機能しますが、ObservativeCollection "Collection"が列幅よりも長いデータで更新された場合、列サイズは自動的に更新されないため、これはデータの初期表示:

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

1
自動サイズの問題の解決策を見つけたことがありますか?私も同じことを経験しています。
オスカー

2
@ Oskar-リストの仮想化は自動解決を防ぎます。リストは現在表示されているアイテムのみを認識し、それに応じてサイズを設定します。リストのさらに下にアイテムがある場合、それはそれらを認識していないため、それらを説明できません。ProgrammingWPF-Sells-Griffithの本では、データバインディングを使用している場合は、手動の列幅を推奨しています。:(
Gishu 2010

おかげ@Gishu、それは実際には理にかなって...
オスカー

MVVMの使用とバインディングの値が変更されている場合は、@ RollfWesselsの回答を参照してください。
ジェイクバーガー

回答:


104

各列のサイズを自動化するには、GridViewColumnでWidth = "Auto"を設定できます。

ID列のテキストを右揃えにするには、TextBlockを使用してセルテンプレートを作成し、TextAlignmentを設定します。次に、ListViewItem.Horizo​​ntalContentAlignmentを(ListViewItemのセッター付きのスタイルを使用して)設定して、セルテンプレートがGridViewCell全体を埋めるようにします。

もっと簡単な解決策があるかもしれませんが、これはうまくいくはずです。

注:このソリューションでは、Window.ResourcesのHorizo​​ntalContentAlignment = StretchとCellTemplateのTextAlignment = Rightの両方が必要です

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

@ Kjetil-この設定を特定の列に適用できますか?
gishu 2010

15
+1 for:<Setter Property = "Horizo​​ntalContentAlignment" Value = "Stretch" />
Helge Klein

素晴らしいですが、15列ありますが、それらすべてに対してセルテンプレートを繰り返す必要がない方法はありますか?
Nitin Chaudhari 2012

7
また、GridViewColumnからDisplayMemberBindingを削除するのを忘れた場合も機能しません。その場合、テンプレートは効果がありません。
floele 2013

@モハメドどうしてじゃないの?
それはNotALieです。

37

コンテンツの幅が変更された場合は、次のコードを使用して各列を更新する必要があります。

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

    column.Width = double.NaN;
}

その列のデータが更新されるたびに起動する必要があります。


1
これを何に付けますか?
Armentage 2010年

1
グリッドデータを更新した後、GridViewColumnで手動で実行します。ViewModelがある場合は、その上でPropertyChangedイベントをサブスクライブして、それを実行できます。
RandomEngy 2010年

+1ありがとうございます!これは私を大いに助けました!この質問とは関係ありませんが、とにかく:GUIを介して実行時に列を動的に追加/削除できるカスタマイズされたList / GridViewを実装しました。ただし、列を削除して再度追加すると、表示されなくなりました。最初は(何らかの理由で)まったく追加されていないと思っていましたが、(Snoopを使用して)実際に追加されていることがわかりましたが、ActualWidthは0です(自動サイズ設定され、列が削除)。ここで、列に再度追加した後、コードを使用して列を正しい幅に設定します。どうもありがとう!
gehho 2010年

私の問題の簡単な解決策!
gqqnbig 2012

+1パーフェクト!これが答えとしてマークされたらいいのに。列が定義されているXAMLにx:Name = "gvcMyColumnName"を追加して、コードビハインドで列にアクセスできるようにしました。チャンピオンのように機能します。
K0D4 2013

19

リストビューのサイズも変更している場合は、動作パターンを使用して、リストビューの全幅に合わせて列のサイズを変更できます。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


これはかっこいいです。問題を解決し、あなたが探しているすべての、n、自動機能を提供します。
デザインパターン2011

これが私が探していたものです。:D
ジェイクバーガー

注:バグがあるようです。ListViewのサイズが垂直方向に変更されると、垂直方向のスクロールバーが表示されるようになり、スクロールバーが消えるまで列の幅が継続的に増加します。
ジェイクバーガー

1
この投稿は、私の以前のコメントで説明されている動作に関する洞察を提供する可能性があります。
ジェイクバーガー

かっこいいです。コードとサイトの両方を意味します:)。より厳しい要件がある場合に役立つと思います。
gqqnbig 2012

12

私は次のクラスを作成し、アプリケーション全体で必要に応じて次の代わりに使用しました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);
    }
}

7

ItemContainerStyleを持っていたので、Horizo​​ntalContentAlignmentを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" /> 
    ....

6

私は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);
    }        
}

2

これは手遅れであることを私は知っていますが、ここに私のアプローチがあります:

<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の幅にバインドすることです。Width = 100は、最初のサイズ変更まで使用されるデフォルトの幅です。背後にコードはありません。すべてがxamlにあります。


これは、1つの列の幅を埋めるためにこのソリューションに私を刺激しました:<GridViewColumn Width = "{Binding RelativeSource = {RelativeSource AncestorType = ListView}、Path = ActualWidth}">
J. Andersen

1

受け入れられた回答に問題がありました(Horizo​​ntalAlignment = Stretch部分を見逃し、元の回答を調整したため)。

これは別のテクニックです。SharedSizeGroupを持つグリッドを使用します。

注:Grid.IsSharedScope =真の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>

GridViewColumnasの幅があり、40列定義の幅をAuto?に設定します。それは意味がありません。
BK

1

リストの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;
    }
}

0

これはあなたのコードです

<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>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.