I have a WPF DataGrid
that contains some data. I would like to set the width of the columns such that the content fits in and never gets cropped (instead, a horizontal scroll bar should become visible). Additionally, I want the DataGrid
to fill the whole place available (I am working with a DockPanel
). I am using the following code (simplified):
<DataGrid ItemsSource="{Binding Table}">
<DataGrid.Columns>
<DataGridTextColumn MinWidth="100" Width="Auto" Header="Column 1" Binding="{Binding Property1}" />
<DataGridTextColumn MinWidth="200" Width="Auto" Header="Column 2" Binding="{Binding Property2}" />
</DataGrid.Columns>
</DataGrid>
This apparently does not work out of the box with Width="Auto"
as it always looks something like this:
This obviously looks ugly. I would like to have the whole row selected, or, which would be much better, the columns to fill the whole width, but as one can see, this does not work.
If I use Width="*"
instead, the content of the columns gets cropped which is even worse for me.
I found a similar question here, and a workaround was posted there. This may work, but I am working with the MVVM pattern, so the ItemsSource gets updated in the ViewModel and I cannot think about a way of doing it from there, because I cannot access the ActualWidth
property of the DataGridColumn
. Also, I would like to do it only in XAML if possible.
I would appreciate any help. Thanks!
Edit: As I still don't have a clue what to do about it, I start a small bounty. I would be very happy about a suggestion what one could do about my problem. Thanks again!
Edit 2: After saus' answer I thought about the options again. The problem is that I need to update the Width
and the MinWidth
properties also during the application is running, so not only after loading the window. I already tried to do something like
column.Width = new DataGridLength(1, DataGridLengthUnitType.Auto);
column.MinWidth = column.ActualWidth;
column.Width = new DataGridLength(1, DataGridLengthUnitType.Star);
in some event that is fired when the underlying ItemsSource
of the DataGrid
is updating. However, this does not work, as the ActualWidth
property does not seem to change after setting the Width
on Auto
. Is there an option to somehow "repaint" it in order to get the ActualWidth
property updated? Thanks!
how about this:
for your columns' MinWidth, you setup a binding to the dataGrid's ScrollContent's Width, with a converter that divide this width by the number of columns
you need some code behind for the converter, but this would keep your MVVM structure intact.
might be a long shot though, did not have the time to try it.
Edit: I put some more thought into this and there a pb: it will not work well if you have, say, one huge column and a few small ones. I assumed that all cols are the same width, which is obviously not the case here.
You might want to explore this way though. Using bindings on the Widths with converters is about the only thing I can think of that could work: since you basically have 2 conditions to take into account when calculating a column's width, there will be no easy way to do this.
I would suggest using the workaround that you linked to. It does work. In the codebehind of your view, add the following to the constructor after InitializeComponent():
and define SetMinWidths as:
I'm assuming that the reason you don't want to use this solution is that you believe that MVVM prohibits code in the codebehind. But since this is entirely view specific logic I believe that it is justified in this case. The whole "MVVM prohibits code in the codebehind" thing is a bit of a misconception.
But if you are bound by style guides, or you want this logic to be available for all datagrids in your app, you can make an attached behaviour that does the job like this:
and then for any datagrid that you want to apply this behaviour to, add the following:
And then your conscience, as well as your codebehind, will be clear.
If you want the column to never cut off your data, add the following to your Window/UserControl definition:
Then for the width of the Columns you can use to following.
This makes the column always grow wide enough to accommodate the longest value in the column.
As the above code didn't work in the DataGrid, what about adding a ScrollViewer around the DataGrid like this:
Use a TextBlock with text wrapping inside template column:
I added the
Event
to theDataGrid
that redefine their width regarding to the actual width of theDataGrid
:The line:
was absolutely senceless. Definition of
DataGridLengthUnitType.Star
shrinks the columns width to their minimum width, and makes their width static and uneditable.Force the last column to take all the remaining space in datagrid