2009-08-19 7 views
2

wpfデータグリッドを使用していて、ユーザーがそれらのいずれかを調整したときにすべての行の高さを設定する方法を探しています。私は、DataGridには行の高さを一度に設定するRowHeightプロパティがあることがわかっていますが、個々の行の高さをキャッチする方法は私をエスケープする方法を変更しましたwpfデータグリッドのすべての行の高さを1行の高さを調整するときに設定する方法

答えて

2

私は試行錯誤してこれに着いたので、あなたはItemsSourceデータソースを使用しているので、正常に動作するはずです。 これは仮想行で動作し、視覚的な一時停止を引き起こすだけでなく、切り替えられます(これは、主に列の自動生成になるので避けることができます)。

ハッキングが進むにつれて、変更が必要ではない単純化とメカニックの使用という利点があります。

アクションのユーザー・トリガーに関するヒューリスティックは改善されるかもしれませんが、まだ私には失敗していません。

using Microsoft.Windows.Controls; 
using Microsoft.Windows.Controls.Primitives; 

public static class DataGridExtensions 
{ 
    public static void LinkRowHeightsToUserChange(this DataGrid dataGrid) 
    { 
     double? heightToApply = null; 
     bool userTriggered = false; 

     if (dataGrid.RowHeaderStyle == null) 
      dataGrid.RowHeaderStyle = new Style(typeof(DataGridRowHeader)); 
     if (dataGrid.RowStyle == null) 
      dataGrid.RowStyle = new Style(typeof(DataGridRow)); 

     dataGrid.RowStyle.Setters.Add(new EventSetter() 
     { 
      Event = DataGridRow.SizeChangedEvent, 
      Handler = new SizeChangedEventHandler((r, sizeArgs) => 
      { 
       if (userTriggered && sizeArgs.HeightChanged) 
         heightToApply = sizeArgs.NewSize.Height; 
      }) 
     }); 
     dataGrid.RowHeaderStyle.Setters.Add(new EventSetter() 
     { 
      Event = DataGridRowHeader.PreviewMouseDownEvent, 
      Handler = new MouseButtonEventHandler(
       (rh,e) => userTriggered = true) 
     }); 
     dataGrid.RowHeaderStyle.Setters.Add(new EventSetter() 
     { 
      Event = DataGridRowHeader.MouseLeaveEvent, 
      Handler = new MouseEventHandler((o, mouseArgs) => 
      { 
       if (heightToApply.HasValue) 
       { 
        userTriggered = false; 
        var itemsSource = dataGrid.ItemsSource; 
        dataGrid.ItemsSource = null; 
        dataGrid.RowHeight = heightToApply.Value; 
        dataGrid.ItemsSource = itemsSource; 
        heightToApply = null; 
       } 
      }) 
     }); 
    } 
+0

これは動作しますが、仮想化がオンの場合は非常に遅いです。 –

+0

申し訳ありませんが、列の仮想化がオフになっているときにオンにした場合、水平方向にスクロールできませんでしたが、行のサイズがうまく調整されました。 –

+0

ええ、私は、誰かが実際にサイズを変更したときにその機能の料金を大幅に支払うのは大変ですが、コストがかかります。 おそらく、何らかの方法で列をキャッシュし、列を再生成せずにソースを削除して再作成できます。 – ShuggyCoUk

3

そのために直接使用できるイベントはありません。行やその他のもののサイズを変更するときに発生する別のイベントを使用することができます。私が今考えているイベントは、Preview MouseUpです。これは、DataGridの場合はどこにでもマウスボタンを放すと解放されます。

あなたができることは、イベントが発生したときに、すべての行の行の高さを確認し、異なる行を見つけてすべての行を更新することです。

1

私の知る限り、行の高さをリサイズするときに発生するイベントはありません。

私の最初の提案はDataGridRowのheightプロパティとDataGridのがRowHeightプロパティ間の結合(片道)を作成するために、RowStyleを設定することです

、しかし あなたはそれのサイズを変更した後、行の高さを確認した場合、それは変更されませんActualHeightは、行の実際の高さをサイズ変更するときにその行のプロパティを含むプロパティであり、「アクセス可能なセットアクセッサを持たない」ためActualHeightを設定できません。

私はこれを試した後、DataGridRowのActualHeightはどこから値を取得するのですか?

クリックしたセルと行を検出する方法を説明しているこのpostと、DataGridのデフォルトのテンプレートビジュアルツリーも示しています。

試行錯誤(上のリンクのビジュアルツリーイメージを使用)では、使用されている高さを格納しているのがDataGridCellPresenterであることがわかりました(実際にはこれについて100%確信していません。 DataGridCell以降、高さが視覚的なツリーに変化しました)。だから私の最初のアプローチは、(ビジュアルツリーを通じて)DataGrid内のすべてのDataGridCellPresenterを取得することでした

はどうやらデータグリッドは、後に(私がhereを見つけたとして)

をDataGridRowからDataGridCellsPresenterを取得するAPIを公開していません。 DataGridPresenterのHeightプロパティとDataGridのRowHeightプロパティの間にバインディングがプログラムで作成されます。ここで

はそれを行うためのコードです(私のDataGridのインスタンス名ははDataGrid1です):このとき、Loadedイベントを呼び出します(それらのすべてにプログラム的にバインディングを設定

void GetAllDataGridCellPresenters(DependencyObject parent, List<DataGridCellsPresenter> presenters) 
    { 
     int numberOfChildren = VisualTreeHelper.GetChildrenCount(parent);   
     for (int i = 0; i < numberOfChildren; i++) 
     { 
      if (VisualTreeHelper.GetChild(parent, i) is DataGridCellsPresenter) 
      { 
       presenters.Add(VisualTreeHelper.GetChild(parent, i) as DataGridCellsPresenter); 
      } 
      else if (VisualTreeHelper.GetChild(parent, i) != null) 
      { 
       GetAllDataGridCellPresenters(VisualTreeHelper.GetChild(parent, i), presenters); 
      } 
      else 
       return; 
     } 
    } 

はすべてDataGridCellPresenterを取得します)データグリッドで発生します

void SetBindingInDataGridPresenter() 
    { 
     List<DataGridCellsPresenter> presenters = new List<DataGridCellsPresenter>(); 
     GetAllDataGridCellPresenters(dataGrid1, presenters); 
     foreach (DataGridCellsPresenter presenter in presenters) 
     {  
      Binding binding = new Binding("RowHeight"); 
      binding.Source = dataGrid1; 
      binding.Mode = BindingMode.TwoWay; 
      presenter.SetBinding(DataGridCellsPresenter.HeightProperty, binding); 
     } 
    } 

(注意:設定結合OneWayToSourceが機能しなかったとして、私は本当に、なぜ、私はおそらくMISSIてるかわかりませんここに明白な何か...)

これはうまくいきました...私はビジュアルツリーを使ってDataGridCellsPresenterを取得しました。私は目に見えるものしか持っていませんでした:しかし、これはこれを行うことができます方法。

最後に、DataGridコントロールテンプレートを提供するのが正しい方法です.DataGridのRowHeightプロパティにバインドされたDataGridCellsPresenterのHeightプロパティデータを除いて、デフォルトのコントロールテンプレートと同じにすることができます。

私はこれを行う方法を正確には分かりませんが、学習する必要があることを知っています(私もそうです:P) 〜redefine a control's template;どういうわけか、デフォルトのDataGridテンプレートを取得しています(すでに、他のものを既に使用している場合は、それ以上のことを知っていて、DataGridCellsPresenter Heightプロパティを自動的にRowHeight DataGridプロパティにバインドする方法を知っています)。その両方の高さのプロパティを取得する魔法のビットでそれを変更します。

2

@Aran

あなたがこの背後にある理論的根拠を覚えていますか?

私はあなたを伝えることができます:あなたは(実際にプロセス全体にかなり遅くなります)項目ソースの設定を解除するに両方の行を削除し、リセットした場合、あなたは、サイズ変更列は、その高さが決定的に設定されています。

行のサイズを変更したときにその高さを直接変更すると、この行のdataGridのRowHeightプロパティに設定した値がオーバーライドされたようです。だから、基本的に、ここにあなたが得ることができるものである。

DataGridのがRowHeight = 20

あなたは=>この行の高さが30に設定され、DataGridのがRowHeightが30に1行(第5回言う)の高さを変更します30に設定されています。

今度は、別の行の高さを20に戻します(2行目など)。この行の高さを20に設定し、DataGrid'RowHeightを20に設定します。これは、他のすべての行を20に設定します(第5行は30に固定されています)。ソースをリセットして、各行を強制的に再ロードし、DataGridのRowHeightを考慮に入れて、問題を解消します。

+0

面白い、それを見ても、それに慣れていない、ありがとう。 –

関連する問題