I have a Grid with 2 columns separated by a GridSplitter using the following XAML code :
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" MinWidth="20" />
<ColumnDefinition Width="10" />
<ColumnDefinition Width="*" MinWidth="100" />
</Grid.ColumnDefinitions>
<Rectangle Fill="Blue" />
<GridSplitter Grid.Column="1" Background="LightGray" HorizontalAlignment="Stretch" />
<Rectangle Fill="Yellow" Grid.Column="2" />
</Grid>
Problem : The MinWidth of the Column on the right is ignored
- I definitely need the first column Width to be "100px" when page loads, so It cannot be * sized.
- I do not want to set a MaxWidth on the first column
*I know that has been adressed before but it always suggest to set column size to * or set a maxWidth on the first column... I don't want that.
Found a solution, but its UGLY! :p, anybody has a cleaner way to achieve what I want... CODELESS (if possible)?
private void Grid_SizeChanged(object sender, SizeChangedEventArgs e)
{
var g = (Grid)sender;
Double maxW = e.NewSize.Width - g.ColumnDefinitions[2].MinWidth - g.ColumnDefinitions[1].ActualWidth;
g.ColumnDefinitions[0].MaxWidth = maxW;
}
The basic problem is that a grid splitter works by adjusting the width of the left column only and assumes the right column will star-size to fit the remaining space.
That means the problem you are trying to solve is actually "how do I limit the max width of the left column so that the right column does not get too small?". This is basically what your code sample is doing.
If you want a more portable solution, that you can implement in XAML, create a Silverlight behavior that can be applied to a grid (as shown below). It will attach to the parent grid's
SizeChanged
event and do pretty much exactly what your code snippet does, but being a behavior you can drag and drop them in Blend or attach them in XAML.Here is a sample behavior I threw together for you as an example (based on your own code):
MinWidthSplitterBehavior.cs
and use it like this:
This seems to me to be a bug in the WPF GridSplitter. The root of the problem is using different types of values for the Width column.
This will not work:
Because column [0] has a width of "100", an explicit number type, and column [1] has a width of "*". But this will work:
When you do this, both the left and right "MinWidth" values are respected by the GridSplitter. To me, this means bug in WPF.
In my case, I need to set the left column to "Auto" with a minimum, and the right to "*" with a minimum, but there doesn't seem to be any way to do that without some form of codebehind. My guess is that the simplest solution will be to just * size everything and use a custom behavior to replace the "auto" functionality of the column (since that is a one-column, one-time fix), but I have yet to do that. Hopefully, the XAML will look something like this:
Update*: I implemented a behavior as noted in this post above. it was not as simple as I was hoping due to Grid limitations. I can not post the solution due to company limitations, but I can give some tips. The biggest problem I ran into is that you can't really get away from star sizing, even with behavior codebehind, because it makes the MinWidth stop working for the star-sized columns.
To compensate for this involved processing all the columns for the grid. You have to take the columns you want auto-sized, determine their children's desired size by getting UIElements by column and using Measure on them, and then changing their star-size-value to a percentage of total available star-size spacing. You also have to adjust non-auto-star-sized columns star-size value accordingly.
As an example, consider a grid with 3 columns: 1st star-sized with MinWidth we want to be auto, 2nd auto-sized without MinWidth, and third star-sized with MinWidth. If the control is 100 units wide, and the content of the first column wants 25 pixels, and the content of the third column wants 5 pixels, the code has to star-size the first and last column as "25*" and "70*" respectively (or any other numbers that get the right ratio).
This was non-trivial, but did work in the end. I did not account for column spanning.
Sorry I can't post the code.