WPF DataGrid:滚动时减小列宽以适合其内容

AsV*_*leO 5 c# wpf datagrid scroll width

滚动垂直滚动条时,DataGrid如果新可见行中的内容较大且超出以前的列宽,则会自动扩展列宽.没关系.

但是,如果滚动所有较大的行并且新的可见行具有较小的内容宽度,DataGrid则不会减小列宽.有办法实现这个吗?

附加的行为实施将是伟大的.

代码behing:

 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; }
        }
    }
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

小智 5

将LoadingRow属性添加到数据网格:

   <DataGrid x:Name="DG"
        CanUserAddRows="False"
        CanUserDeleteRows="False"
        CanUserReorderColumns="False"
        CanUserResizeColumns="False"
        CanUserResizeRows="False"
        CanUserSortColumns="False" LoadingRow="DG_LoadingRow">
    </DataGrid>
Run Code Online (Sandbox Code Playgroud)

然后在后面的代码中添加这段代码:

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;
    }
Run Code Online (Sandbox Code Playgroud)

这绝对不是最干净的解决方案,但它会调整滚动时可见的列的大小。

希望这可以帮助。


您能否将其包装到附加行为中?

1)第一个选项是使用Attached Property

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

用法

<DataGrid
    ext:DataGridHelper.SyncedColumnWidths="True"
    ... />
Run Code Online (Sandbox Code Playgroud)

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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

用法

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

...

    <DataGrid
        ... >
        <i:Interaction.Behaviors>
            <ext:SyncedColumnWidthsBehavior />
        </i:Interaction.Behaviors>
    </DataGrid>
Run Code Online (Sandbox Code Playgroud)

行为提供了一种释放事件处理程序的干净方法。尽管在这种情况下,即使我们不取消订阅附加属性,我们也不会造成内存泄漏(参考不取消注册事件处理程序是否不好?)。

  • 提示,还有一个 `e.Row.UpdateLayout()` (3认同)