2009-05-10 18 views
17

私はListView WPFコントロールにGridViewを持っています。私はGridView列の内容が変更されたときに列のサイズを変更したいと思います。ListView内のGridView列の強制的なサイズ変更

私はいくつかの異なるデータセットを持っていますが、私が1つから別のものに変更すると、各カラムのサイズは以前のデータに適合します。私は動的に更新したいと思います。どうやってやるの?

+2

私も同じ問題があります。データソースを変更すると、列の幅のサイズが変更されません。私は、ソースを設定してAutoSizeColumnsメソッドなどを呼び出すことに満足しています。 –

+0

+1、これは私をナッツ運転しています! – Oskar

答えて

-1

あなたはピクセル単位で最長の文字列を測定し、それに応じて、列幅を調整することができます:

Graphics graphics = this.CreateGraphics(); 
SizeF textSize = graphics.MeasureString("How long am I?", this.Font); 

あなたはこれらの長さの比として各列をサイズ変更するためのアルゴリズムを作成した場合、あなたは良い結果を取得する必要があります。

+0

これはWPFとバインディングではうまくいきません。 –

29

最後に、今回はいくつかの結果が得られました。私は、最初に行われたのと同じ自動サイズ設定を行う方法と、列ヘッダーのグリッパーをダブルクリックする方法を見つけました。

public void AutoSizeColumns() 
{ 
    GridView gv = listView1.View as GridView; 
    if (gv != null) 
    { 
     foreach (var c in gv.Columns) 
     { 
      // Code below was found in GridViewColumnHeader.OnGripperDoubleClicked() event handler (using Reflector) 
      // i.e. it is the same code that is executed when the gripper is double clicked 
      if (double.IsNaN(c.Width)) 
      { 
       c.Width = c.ActualWidth; 
      } 
      c.Width = double.NaN; 
     } 
    } 
} 
+0

素晴らしい解決策です。ありがとう。 –

1

カラムのActualWidthにバインドする方法はありませんか?何かが好きです:

<GridViewColumn x:Name="column1" Width="{Binding ElementName=column1, Path=ActualWidth}" /> 

私はこれを試して初めて動作します。バインドエラーはありません。

+0

私も試したことがあります: Width = "{バインディングパス= ActualWidth、RelativeSource = {x:静的RelativeSource.Self}}" – Thia

+0

ええ、ActualWidthをWidthにコピーします。自動サイズ調整は初めて無効になります。 ActualWidthは決して再び変更されないので、意図した幅も変更されません。 – ygoe

4

Oskarsの答えをもとに、コンテンツの変更時に自動的に列のサイズを調整するブレンド動作を示します。

/// <summary> 
/// A <see cref="Behavior{T}"/> implementation which will automatically resize the automatic columns of a <see cref="ListView">ListViews</see> <see cref="GridView"/> to the new content. 
/// </summary> 
public class GridViewColumnResizeBehaviour : Behavior<ListView> 
{ 
     /// <summary> 
     /// Listens for when the <see cref="ItemsControl.Items"/> collection changes. 
     /// </summary> 
     protected override void OnAttached() 
     { 
      base.OnAttached(); 

      var listView = AssociatedObject; 
      if (listView == null) 
       return; 

      AddHandler(listView.Items); 
     } 

     private void AddHandler(INotifyCollectionChanged sourceCollection) 
     { 
      Contract.Requires(sourceCollection != null); 

      sourceCollection.CollectionChanged += OnListViewItemsCollectionChanged; 
     } 

     private void RemoveHandler(INotifyCollectionChanged sourceCollection) 
     { 
      Contract.Requires(sourceCollection != null); 

      sourceCollection.CollectionChanged -= OnListViewItemsCollectionChanged; 
     } 

     private void OnListViewItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs) 
     { 
      var listView = AssociatedObject; 
      if (listView == null) 
       return; 

      var gridView = listView.View as GridView; 
      if (gridView == null) 
       return; 

      // If the column is automatically sized, change the column width to re-apply automatic width 
      foreach (var column in gridView.Columns.Where(column => Double.IsNaN(column.Width))) 
      { 
       Contract.Assume(column != null); 
       column.Width = column.ActualWidth; 
       column.Width = Double.NaN; 
      } 
     } 

     /// <summary> 
     /// Stops listening for when the <see cref="ItemsControl.Items"/> collection changes. 
     /// </summary> 
     protected override void OnDetaching() 
     { 
      var listView = AssociatedObject; 
      if (listView != null) 
       RemoveHandler(listView.Items); 

      base.OnDetaching(); 
     } 
} 
+0

この動作は、新しい 'ActualWidth'が計算されるまでに時間がかかることを考慮していません。したがって、 'ActualWidth'は依然として内容に合うほど小さすぎることがあります。 – Danielku15

+0

@ Danielku15あなたはそれが起こっていることを知っていますか?私はこの問題を解決するために働くことができるので、小さなサンプルが素晴らしいだろう。 – Lukazoid

+1

私はObservableCollectionにバインドされたListViewを持っています。私は40x40ptである私のCellTemplateのコントロールを持っています。ビヘイビアをアタッチするとOnListViewItemsCollectionChangedメソッドが実行されますが、ActualWidthはまだ小さすぎます(私の場合は25pt)。結果:それは切り取られます。ハンドラが実行されたときにレイアウトプロセスが実行されなかったようです。 – Danielku15

1

私のような古いであり、ここではその後、VB.NETを希望する場合は、Oskarsコードだ:

Public Sub AutoSizeColumns() 
    Dim gv As GridView = TryCast(Me.listview1.View, GridView) 
    If gv IsNot Nothing Then 
     For Each c As GridViewColumn In gv.Columns 
      If Double.IsNaN(c.Width) Then 
       c.Width = c.ActualWidth 
      End If 
      c.Width = Double.NaN 
     Next 
    End If 
End Sub 

これは、WPFで素晴らしい作品、ついに誰かがこれを働いています。オスカーに感謝します。

関連する問題