WPF DataGrid: уменьшите ширину столбца, чтобы соответствовать его содержимому при прокрутке - PullRequest
0 голосов
/ 09 декабря 2018

Когда я прокручиваю вертикальную полосу прокрутки, DataGrid автоматически увеличивает ширину столбца, если содержимое новых видимых строк больше и превышает ширину предыдущего столбца.Это нормально.

Но если прокрутить все большие строки и новые видимые строки имеют небольшую ширину содержимого, DataGrid не уменьшает ширину столбца.Есть ли способ архивировать это?

Реализация присоединенного поведения будет отличной.

Кодировка:

 public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();
            var persons = new List<Person>();
            for (var i = 0; i < 20; i++)
                persons.Add(new Person() {Name = "Coooooooooooooool", Surname = "Super"});
            for (var i = 0; i < 20; i++)
                persons.Add(new Person() {Name = "Cool", Surname = "Suuuuuuuuuuuuuuper"});
            for (var i = 0; i < 20; i++)
                persons.Add(new Person() {Name = "Coooooooooooooool", Surname = "Super"});
            DG.ItemsSource = persons;
        }

        public class Person
        {
            public string Name { get; set; }
            public string Surname { get; set; }
        }
    }

XAML:

<Window
    x:Class="WpfApp4.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="400"
    Height="200"
    mc:Ignorable="d">
    <Grid>
        <DataGrid
            x:Name="DG"
            CanUserAddRows="False"
            CanUserDeleteRows="False"
            CanUserReorderColumns="False"
            CanUserResizeColumns="False"
            CanUserResizeRows="False"
            CanUserSortColumns="False" />
    </Grid>
</Window>

Ответы [ 2 ]

0 голосов
/ 13 декабря 2018

Извините за задержку, чтобы ответить на ваш вопрос.

Мой метод заключается в захвате видимой строки на экране, получении средней ширины и назначении ширины столбцов.

Первая подписка на событие ScrollChanged ScrollViewer's.

       <DataGrid
        ScrollViewer.ScrollChanged="DG_ScrollChanged"
        x:Name="DG"
        CanUserAddRows="False"
        CanUserDeleteRows="False"
        CanUserReorderColumns="False"
        CanUserResizeColumns="False"
        CanUserResizeRows="False"
        CanUserSortColumns="False" />
</Grid>

Используя ScrollChanged и FindVisualChildren, я могу получить вертикальное смещение.

мы можем получить индекс строки из вертикального смещения, а индекс последней строки рассчитывается с использованием (int) scroll.VerticalOffset + (int) scroll.ViewportHeight - 1

     ScrollViewer scroll = null;
    private void DG_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        // get the control once and then use its offset to get the row index
        if (scroll == null)
            scroll = MethodRepo.FindVisualChildren<ScrollViewer>((DependencyObject)sender).First(); 

        int firstRow = (int)scroll.VerticalOffset;
        int lastRow = (int)scroll.VerticalOffset + (int)scroll.ViewportHeight + 1;

        List<int> FirstColumnLength = new List<int>();
        List<int> SecondColumnLength = new List<int>();
        for (int i = firstRow; i < lastRow-1; i++)
        {
            FirstColumnLength.Add(Convert.ToString(persons[i].Name).Length);
            SecondColumnLength.Add(Convert.ToString(persons[i].Surname).Length);
        }

        DG.Columns[0].Width = FirstColumnLength.Max()*10;
        DG.Columns[1].Width = SecondColumnLength.Max() * 10;
    }

Я такжесоздал статический класс для получения потомков Visual.

 public static class MethodRepo
{
    public static IEnumerable<T> FindVisualChildren<T>([NotNull] this DependencyObject parent) where T : DependencyObject
    {
        if (parent == null)
            throw new ArgumentNullException(nameof(parent));

        var queue = new Queue<DependencyObject>(new[] { parent });

        while (queue.Any())
        {
            var reference = queue.Dequeue();
            var count = VisualTreeHelper.GetChildrenCount(reference);

            for (var i = 0; i < count; i++)
            {
                var child = VisualTreeHelper.GetChild(reference, i);
                if (child is T children)
                    yield return children;

                queue.Enqueue(child);
            }
        }
    }
}

enter image description here

0 голосов
/ 13 декабря 2018

Добавьте свойство LoadingRow . Datagrid:

   <DataGrid x:Name="DG"
        CanUserAddRows="False"
        CanUserDeleteRows="False"
        CanUserReorderColumns="False"
        CanUserResizeColumns="False"
        CanUserResizeRows="False"
        CanUserSortColumns="False" LoadingRow="DG_LoadingRow">
    </DataGrid>

А затем добавьте этот код в код:

private void DG_LoadingRow(object sender, DataGridRowEventArgs e)
    {
        foreach (DataGridColumn c in DG.Columns)
            c.Width = 0;

        DG.UpdateLayout();

        foreach (DataGridColumn c in DG.Columns)
            c.Width = DataGridLength.Auto;
    }

Это определенно не самый чистыйрешение, но это изменит размер столбцов, которые отображаются во время прокрутки.

Надеюсь, это поможет.


Не могли бы вы заключить это в прикрепленное поведение?

1) Первый вариант - использовать Присоединенное свойство .

public class DataGridHelper : DependencyObject
{
    public static readonly DependencyProperty SyncedColumnWidthsProperty =
        DependencyProperty.RegisterAttached(
          "SyncedColumnWidths",
          typeof(Boolean),
          typeof(DataGridHelper),
          new FrameworkPropertyMetadata(false,
              FrameworkPropertyMetadataOptions.AffectsRender,
              new PropertyChangedCallback(OnSyncColumnsChanged)
          ));

    private static void OnSyncColumnsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is DataGrid dataGrid)
        {
            dataGrid.LoadingRow += SyncColumnWidths;
        }
    }

    private static void SyncColumnWidths(object sender, DataGridRowEventArgs e)
    {
        var dataGrid = (DataGrid)sender;

        foreach (DataGridColumn c in dataGrid.Columns)
            c.Width = 0;

        e.Row.UpdateLayout();

        foreach (DataGridColumn c in dataGrid.Columns)
            c.Width = DataGridLength.Auto;
    }

    public static void SetSyncedColumnWidths(UIElement element, Boolean value)
    {
        element.SetValue(SyncedColumnWidthsProperty, value);
    }
}

Использование

<DataGrid
    ext:DataGridHelper.SyncedColumnWidths="True"
    ... />

2) В качестве альтернативы Поведения обеспечивают более инкапсулированный способ расширения функциональности (требуется System.Windows.Interactivity ).

using System.Windows.Interactivity;

...

    public class SyncedColumnWidthsBehavior : Behavior<DataGrid>
    {
        protected override void OnAttached()
        {
            this.AssociatedObject.LoadingRow += this.SyncColumnWidths;
        }

        protected override void OnDetaching()
        {
            this.AssociatedObject.LoadingRow -= this.SyncColumnWidths;
        }

        private void SyncColumnWidths(object sender, DataGridRowEventArgs e)
        {
            var dataGrid = this.AssociatedObject;

            foreach (DataGridColumn c in dataGrid.Columns)
                c.Width = 0;

            e.Row.UpdateLayout();

            foreach (DataGridColumn c in dataGrid.Columns)
                c.Width = DataGridLength.Auto;
        }
    }

Использование

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

...

    <DataGrid
        ... >
        <i:Interaction.Behaviors>
            <ext:SyncedColumnWidthsBehavior />
        </i:Interaction.Behaviors>
    </DataGrid>

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

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