Basically, I’d like to make the WPF DataGrid control layout its columns exactly the way the WinForms DataGridView does
And more specifically, here is the behaviour I’m looking for:
-
The grid control should take up the space it’s given (i.e. however much space is available in its parent control for it to use). Here I am referring just to the control, and not to the columns.
-
The columns created (whether automatically or manually) may or may not take up all this space.
-
If there is extra space left over after the columns are created, the last column should not be expanded to fill this space
-
If there is extra space left over after the columns are created, an empty column with nothing in it should not be created to fill this extra space
From what I can tell, in WPF the last two bullet points seem to be mutually exclusive and you must choose one or the other. Has anyone found a way to do both? I’ve searched quite a bit and haven’t found quite what I’m looking for, however all the posts I’m finding tend to be a couple years old so I’m hoping someone has figured this thing out by now.
EDIT: sa_ddam213, here’s a quick xaml project I put together to test your suggestion.
<Window x:Class="DataGridFix.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DataGridFix"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ObjectDataProvider x:Key="data"
ObjectType="{x:Type local:TestObject}"
MethodName="GetTestData" />
</Window.Resources>
<StackPanel>
<DataGrid HorizontalAlignment="Left" ColumnWidth="Auto" Height="150" VerticalAlignment="Top" ItemsSource="{Binding Source={StaticResource data}}" />
</StackPanel>
</Window>
And here’s the code behind:
namespace DataGridFix
{
public class TestObject
{
public int Id { get; set; }
public string Name { get; set; }
public static List<TestObject> GetTestData()
{
var items = new List<TestObject>();
items.Add(new TestObject() { Id = 1, Name = "Joe" });
items.Add(new TestObject() { Id = 2, Name = "Matt" });
items.Add(new TestObject() { Id = 3, Name = "Hal" });
return items;
}
}
}
Really the only noteable thing I see from your suggestion is to set HorizontalAlignment to Left. I did that, and tried setting the ColumnWidth to the various settings but had the same problem with each (except * of course… technically I can mess that one up to but I won’t go into that).
If you use your mouse to expand any of the columns, and then decrease the column size then the empty filler column appears. The only other difference I noted from your post was that you put your DataGrids in a StackPanel since you had more than one of them. I tried that just for the heck of it but same result. If you see any other difference between what I’m doing and what you suggested please let me know.
In order to get the behavior you want, you probably have to modify the control template of the
DataGrid.Take a look at the code. I have gotten pretty close to the WinForms
DataGridViewlook i think.To remove the extra column you have to remove the filler column from the
DataGridColumnHeadersPresenter. I have just commented it out. The rest is just the default template.The other modification is to the template of the
DataGrid.By setting
HorizontalAlignment="Left"on theScrollContentPresenter, the rows no longer take up all the width of the control.Those are the only 2 changes I have made to the default templates.
UPDATE
It does indeed look like there is a difference between .NET 4 and .NET 4.5.
I develop on a Windows 8 machine with Visual Studio 2012, so as a test I tried targeting .NET 4 to see if I could replicate the wrong behavior. But it still worked fine.
To be sure, I tried running the app on a different machine with only .NET 4 installed, and here the empty rows showed up when making a column bigger and then smaller again.
The issue seems to be that the
DataGridRowsare not behaving properly. When running on a machine with only .NET 4 installed, they keep their current size when making the column smaller. On .NET 4.5 they resize as expected.The new solution to get the behavior you need, is actually much simpler than the previous one.
By simply setting the
HorizontalAlignmenton theDataGridRowstoleft, and removing the filler column, it works on both .NET 4 and .NET 4.5. And there is no longer a need to replace the entire template of theDataGrid.