When I scroll vertical scrollbar, DataGrid
automatically expands column width if content in new visible rows is bigger and exceeds previous column width. It's OK.
But if all bigger rows are scrolled over and new visible ones have small content width, DataGrid
does not decrease column width. Is there a way to archieve this?
Attached behaviour implementation will be great.
Code 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; }
}
}
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>
Add the LoadingRow property to you Datagrid:
<DataGrid x:Name="DG"
CanUserAddRows="False"
CanUserDeleteRows="False"
CanUserReorderColumns="False"
CanUserResizeColumns="False"
CanUserResizeRows="False"
CanUserSortColumns="False" LoadingRow="DG_LoadingRow">
</DataGrid>
And then add this code in the code behind:
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;
}
It's definitely not the cleanest solution but it will resize the columns that are in view while scrolling.
Hope this helps.
Can you please wrap this into attached behaviour?
1) First option is to use an 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);
}
}
Usage
<DataGrid
ext:DataGridHelper.SyncedColumnWidths="True"
... />
2) Alternatively, Behaviors provide a more encapsulated way to extend functionality (requires 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;
}
}
Usage
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
...
<DataGrid
... >
<i:Interaction.Behaviors>
<ext:SyncedColumnWidthsBehavior />
</i:Interaction.Behaviors>
</DataGrid>
Behaviors offer a clean way to release event handlers. Although, in this case, even when we don't unsubscribe with the attached property, we wouldn't create memory leaks (ref Is it bad to not unregister event handlers?).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With