Как сделать так, чтобы последний столбец в таблице данных WPF всегда занимал все оставленное место? - PullRequest
28 голосов
/ 08 декабря 2010

Стандартный WPF 4 Датагрид.

Допустим, у меня есть сетка данных шириной 200 пикселей и 2 столбца. Мне бы хотелось, чтобы столбцы всегда занимали все пространство, то есть если пользователь изменяет размер первого столбца до 50 пикселей, последний из них будет 150.

Первоначально я установил ширину 100 пикселей для 1-го столбца и * для последнего (в XAML).

Я думал, что проблема в удалении виртуального 3-го столбца, как описано здесь:

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

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

ВОПРОС : как применить ограничение, независимо от того, как пользователь изменяет размеры столбцов,

sum(columns width)==datagrid width

редактирует

Да, я использую WPF 4.

* 1026 Временное решение *

Я пометил один из ответов как решение, но на самом деле это не решение из-за дизайна WPF. Это просто то, что WPF может делать в лучшем случае, и это не очень хорошо - прежде всего, опция CanUserResize для столбца означает действительно IsResizeable, и эта опция при включении противоречит Width, установленному в *. Так что без какой-то действительно хитрой уловки вы получите:

  • datagrid, последний столбец которого имеет поверхностно изменяемый размер, но на самом деле это не так, и отображается небольшое пространство справа (т. Е. Виртуальный столбец не имеет изменяемого размера) - для последнего столбца: CanUserResize = true, Width = *

  • datagrid, последний столбец которого не может быть изменен пользователем, и он отображается соответственно, изначально не отображается пробел справа, но он может отображаться, когда пользователь изменяет размер любого элемента таблицы данных - для последнего столбца: CanUserResize = false , Ширина = *

Пока что я вижу две проблемы с сеткой данных WPF:

  • вводящее в заблуждение название
  • противоречие особенностей

Я до сих пор не могу понять, как на самом деле решить эту проблему.

Ответы [ 4 ]

21 голосов
/ 08 декабря 2010

Установите ширину сетки данных на «Авто». Вы разрешаете корректное изменение размера столбцов внутри самой сетки, но вы жестко установили ширину до 200.

ОБНОВЛЕНИЕ : Основываясь на комментарии @ micas, возможно, я неправильно прочитал. Если это так, попробуйте использовать 100 для ширины левого столбца и 100 * для правого столбца (обратите внимание на звездочку). По умолчанию ширина для правого столбца будет равна 100, но при этом размер будет изменяться, чтобы заполнить сетку.

6 голосов
/ 09 декабря 2010

Вы можете установить ширину столбца для пометки в коде. В вашем конструкторе добавьте:

    Loaded += (s, e) => dataGrid1.Columns[3].Width =
new DataGridLength(1, DataGridLengthUnitType.Star);
4 голосов
/ 17 июля 2013

Я только что реализовал это как прикрепленное поведение. Проблема в том, что когда вы устанавливаете последний столбец 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));
        }
    }
}
0 голосов
/ 10 июня 2015

Будьте предупреждены: это хак ....

Я зарегистрировался в событии "AutoGeneratedColumns" в методе "OnLastColumnFillChanged" Dr.Класс ABT и скопировал в него метод 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 с переменным числом столбцов иметь ширину, равную ширине заголовка столбца.Я удалил эту часть, и теперь она, кажется, работает со всеми DataGrids в приложении.

Теперь у меня есть:

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

    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...