1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WPFのDataGridの列幅をリセットしたい

Posted at

0. はじめに

Freeradicalの中の人、yamarahです。
DataGridの列幅は、自動で拡張はすれど、縮小はしないです。列幅が*であり、初回表示前に全てのデータが入っていれば適切にレイアウトされるんですが、後から行を追加すると「列2の幅は余裕があるんだから縮めて、列3の幅を広くしてくれよ」って感じになることが多々あります。

何が問題で、原因なのかは以下が詳しい。

幅が*の列幅を一旦ゼロにして、UpdateLayout()した後に列幅を*に戻すと、良い感じに再レイアウトされます。
コードビハインドはいやなので、behaviorを作りました。

1. DataGridの列幅をリセットするbehavior

using Microsoft.Xaml.Behaviors;
using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace Freeradical.Windows.Behaviors;

public class RefreshDataGridColumnWidthsBehavior : Behavior<DataGrid>
{
    public static readonly DependencyProperty RefreshColumnWidthsCommandProperty = DependencyProperty.Register(
        nameof(RefreshColumnWidthsCommand),
        typeof(ICommand),
        typeof(RefreshDataGridColumnWidthsBehavior),
        new PropertyMetadata(null));

    public ICommand RefreshColumnWidthsCommand
    {
        get => (ICommand)GetValue(RefreshColumnWidthsCommandProperty);
        set => SetValue(RefreshColumnWidthsCommandProperty, value);
    }
    protected override void OnAttached()
    {
        base.OnAttached();
        RefreshColumnWidthsCommand = new RefreshColumnWidths(AssociatedObject);
    }
    protected class RefreshColumnWidths(DataGrid dataGrid) : ICommand
    {
        public event EventHandler? CanExecuteChanged;
        protected readonly DataGrid AssociatedObject = dataGrid;

        public bool CanExecute(object? parameter)
        {
            return true;
        }
        public void Execute(object? parameter)
        {
            var starWidthColumns = AssociatedObject.Columns
                .Select((x, index) => (index, x.Width))
                .Where(pair => pair.Width.IsStar)
                .Select(pair => (pair.index, pair.Width.Value))
                .ToArray();
            foreach ((var index, _) in starWidthColumns)
            {
                AssociatedObject.Columns[index].Width = 0;
            }
            AssociatedObject.UpdateLayout();
            foreach ((var index, var value) in starWidthColumns)
            {
                AssociatedObject.Columns[index].Width = new DataGridLength(value, DataGridLengthUnitType.Star);
            }
        }
    }
}

命名がダサいので、各自リファクタリングしてください。名前空間も。
使い方は、

<Window (中略)
        xmlns:i="clr-namespace:Microsoft.Xaml.Behaviors;assembly=Microsoft.Xaml.Behaviors"
        xmlns:behaviors="clr-namespace:Freeradical.Windows.Behaviors"
        (中略)>
    <DataGrid (中略)>
        <i:Interaction.Behaviors>
            <behaviors:RefreshDataGridColumnWidthsBehavior RefreshColumnWidthsCommand="{Binding RefreshDataGridColumnWidthsCommand, Mode=OneWayToSource}"/>
        </i:Interaction.Behaviors>
        (中略)
    </DataGrid>
</Window>

みたいな感じで。
あとは、ViewModelで

public ICommand? RefreshDataGridColumnWidthsCommand { get; set; }

RefreshDataGridColumnWidthsCommand?.Execute(this);

とすれば、良い感じに再レイアウトされます。やったね!

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?