web-dev-qa-db-ja.com

WPFデータグリッドの最後の列に常に左側のスペースをすべて使用させる方法は?

標準WPF 4データグリッド。

幅200ピクセル、2列のデータグリッドがあるとします。列が常に全体のスペースを取ることを望みます。つまり、ユーザーが最初の列のサイズを50ピクセルに変更すると、最後の列は150になります。

最初に、最初の列に幅100ピクセルを設定し、最後の列に*(XAMLで)幅を設定しました。

ここで説明するように、問題は仮想の3列目を削除することだと思いました。

http://wpf.codeplex.com/Thread/View.aspx?ThreadId=58939

しかし、実際には違いはありません-それでも、列のサイズを変更すると、右側に余分なスペースが表示されます-仮想列では、仮想列(デフォルトでは白色)ですが、それがないと、空白(灰色で表示)になりますデフォルト)。

[〜#〜] question [〜#〜]:ユーザーが列のサイズを変更する方法に関係なく、制約を適用する方法、

sum(columns width)==datagrid width

編集

はい、WPF 4を使用しています。

[〜#〜]回避策[〜#〜]

私は答えの1つをソリューションとしてマークしましたが、実際にはWPFの設計によりソリューションではありません。これは単にWPFで実行できることであり、あまり良くありません。まず、列のオプションCanUserResizeは本当にIsResizeableを意味し、このオプションをオンにすると、Widthが*に設定されていると矛盾します。したがって、いくつかの本当に賢いトリックがなければ、最終的には次のようになります。

  • 表面的にサイズ変更可能な最後の列のデータグリッドですが、実際には変更できず、右側のスペースがほとんど表示されません(つまり、仮想列はサイズ変更できません)-最後の列の場合:CanUserResize = true、Width = *

  • ユーザーが最後の列をサイズ変更できないdatagridとそれに応じて表示されます。最初は右側にスペースは表示されませんが、ユーザーがdatagridの要素のサイズを変更すると表示されます-最後の列の場合:CanUserResize = false、Width = *

これまでのところ、WPFデータグリッドには2つの問題があります。

  • 誤解を招くような命名
  • 機能の矛盾

この問題を本当に解決する方法について、私はまだ耳を傾けています。

28
greenoldman

データグリッドの幅を「自動」に設定します。グリッド自体の中で列のサイズを正しく変更できるようにしていますが、幅を200に固定しています。

[〜#〜] update [〜#〜]:@micasのコメントに基づいて、誤解している可能性があります。その場合は、左の列の幅に100を使用し、右の列に100 *を使用してみてください(アスタリスクに注意してください)。これにより、デフォルトで右の列の幅が100になりますが、グリッドに合わせてサイズを変更できます。

21
Babak Naffas

列幅を設定してコードにスターを付けることができます。コンストラクターに以下を追加します。

    Loaded += (s, e) => dataGrid1.Columns[3].Width =
new DataGridLength(1, DataGridLengthUnitType.Star);
6
biju

これを添付ビヘイビアとして実装しました。問題は、DataGridの最後の列を*に設定すると、それに合わせてサイズが変更されますが、他のセルのすべての自動調整が失敗します。これを解決するために、添付の動作は他の(最後ではない)セルの手動自動調整を行います。

これは、他の列のサイズを変更するときにも機能します。一度読み込まれると、サイズを変更でき、最後の列は常に塗りつぶされます。この動作はLoadedイベントで一度だけ機能することに注意してください

// Behavior usage: <DataGrid DataGridExtensions.LastColumnFill="True"/>
public class DataGridExtensions
{
    public static readonly DependencyProperty LastColumnFillProperty = DependencyProperty.RegisterAttached("LastColumnFill", typeof(bool), typeof(DataGridExtensions), new PropertyMetadata(default(bool), OnLastColumnFillChanged));

    public static void SetLastColumnFill(DataGrid element, bool value)
    {
        element.SetValue(LastColumnFillProperty, value);
    }

    public static bool GetLastColumnFill(DataGrid element)
    {
        return (bool)element.GetValue(LastColumnFillProperty);
    }

    private static void OnLastColumnFillChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var dataGrid = d as DataGrid;
        if (dataGrid == null) return;

        dataGrid.Loaded -= OnDataGridLoaded;
        dataGrid.Loaded += OnDataGridLoaded;
    }        

    private static void OnDataGridLoaded(object sender, RoutedEventArgs e)
    {
        var dataGrid = sender as DataGrid;
        if (dataGrid == null) return;

        var lastColumn = dataGrid.Columns.LastOrDefault();
        if(lastColumn != null)
            lastColumn.Width = new DataGridLength(1, DataGridLengthUnitType.Star);

        // Autofit all other columns
        foreach (var column in dataGrid.Columns)
        {
            if (column == lastColumn) break;

            double beforeWidth = column.ActualWidth;
            column.Width = new DataGridLength(1, DataGridLengthUnitType.SizeToCells);
            double sizeCellsWidth = column.ActualWidth;
            column.Width = new DataGridLength(1, DataGridLengthUnitType.SizeToHeader);
            double sizeHeaderWidth = column.ActualWidth;
            column.MinWidth = Math.Max(beforeWidth, Math.Max(sizeCellsWidth, sizeHeaderWidth));
        }
    }
}
4
Dr. ABT

これは非常に単純な答えで、すべてコードビハインドで実行されます。 :-)すべての列は自動サイズ調整されます。最後の列は残りのすべてのスペースを埋めます。

// build your datasource, e.g. perhaps you have a:
List<Person> people = ...

// create your grid and set the datasource
var dataGrid = new DataGrid();
dataGrid.ItemsSource = people;

// set AutoGenerateColumns to false and manually define your columns
// this is the price for using my solution :-)
dataGrid.AutoGenerateColumns = false;

// example of creating the columns manually.
// there are obviously more clever ways to do this 
var col0 = new DataGridTextColumn();
col0.Binding = new Binding("LastName");
var col1 = new DataGridTextColumn();
col1.Binding = new Binding("FirstName");
var col2 = new DataGridTextColumn();
col2.Binding = new Binding("MiddleName");
dataGrid.Columns.Add(col0);
dataGrid.Columns.Add(col1);
dataGrid.Columns.Add(col2);

// Set the width to * for the last column
col2.Width = new DataGridLength(1, DataGridLengthUnitType.Star);

0
Jay

注意してください:それはハックです...

Dr。ABT のクラスの "OnLastColumnFillChanged"メソッドの "AutoGeneratedColumns"イベントに登録し、Loadedメソッドをそのクラスにコピーしました。まだ十分にテストしていないので、YMMVを使用します。

私の変更:

    private static void OnLastColumnFillChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var dataGrid = d as DataGrid;
        if (dataGrid == null) return;

        dataGrid.Loaded -= OnDataGridLoaded;
        dataGrid.Loaded += OnDataGridLoaded;

        dataGrid.AutoGeneratedColumns -= OnDataGrid_AutoGeneratedColumns;
        dataGrid.AutoGeneratedColumns += OnDataGrid_AutoGeneratedColumns;
    }

    private static void OnDataGrid_AutoGeneratedColumns(object sender, EventArgs e)
    {
        var dataGrid = sender as DataGrid;
        if (dataGrid == null) return;

        var lastColumn = dataGrid.Columns.LastOrDefault();
        if (lastColumn != null)
            lastColumn.Width = new DataGridLength(1, DataGridLengthUnitType.Star);

        // Autofit all other columns
        foreach (var column in dataGrid.Columns)
        {
            if (column == lastColumn) break;

            double beforeWidth = column.ActualWidth;
            column.Width = new DataGridLength(1, DataGridLengthUnitType.SizeToCells);
            double sizeCellsWidth = column.ActualWidth;
            column.Width = new DataGridLength(1, DataGridLengthUnitType.SizeToHeader);
            double sizeHeaderWidth = column.ActualWidth;
            column.MinWidth = Math.Max(beforeWidth, Math.Max(sizeCellsWidth, sizeHeaderWidth));
        }
    }

ああ、名前空間をXAML宣言に追加することを忘れないでください! :)

トップ:

xmlns:ext="clr-namespace:TestProject.Extensions"

そして、DataGrid宣言で:

ext:DataGridExtensions.LastColumnFill="True"

更新:走行距離は変わると言いました!私は確かにそうしました。

その「列の自動調整」ビット全体が原因で、可変数の列を持つDataGridの一部の列は、列ヘッダーと同じ幅しかありませんでした。その部分を削除しましたが、アプリケーションのすべてのDataGridで機能しているようです。

今私が持っています:

    private static void OnDataGrid_AutoGeneratedColumns(object sender, EventArgs e)
    {
        var dataGrid = sender as DataGrid;
        if (dataGrid == null) return;

        UpdateColumnWidths(dataGrid);

    }

    private static void OnDataGridLoaded(object sender, RoutedEventArgs e)
    {
        var dataGrid = sender as DataGrid;
        if (dataGrid == null) return;

        UpdateColumnWidths(dataGrid);
    }

    private static void UpdateColumnWidths(DataGrid dataGrid)
    {
        var lastColumn = dataGrid.Columns.LastOrDefault();
        if (lastColumn == null) return;

        lastColumn.Width = new DataGridLength(1.0d, DataGridLengthUnitType.Star);

    }
0
pennyrave