Question

I have a simple grid with 3 columns (one of which contains a grid splitter). When resizing the grid and the left column reaches its minimum width, instead of doing nothing it increases the width of the right column. Could anyone help me stop this?

I can't set the max width of the right column, because the grid itself also resizes.

Here's some sample code that shows the problem. While resizing, move the mouse over the red area:

XAML:

<Grid DockPanel.Dock="Top" Height="200">
    <Grid.ColumnDefinitions>
        <ColumnDefinition MinWidth="200" Width="*" />
        <ColumnDefinition Width="3" />
        <ColumnDefinition MinWidth="120" Width="240" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Rectangle Fill="Red" Grid.Row="0" Grid.Column="0" />
    <DockPanel LastChildFill="True" Grid.Row="0" Grid.Column="2" >
        <Rectangle DockPanel.Dock="Right" Width="20" Fill="Blue" />
        <Rectangle Fill="Green" />
    </DockPanel>
    <GridSplitter Background="LightGray" Grid.Row="0" Grid.Column="1" Height="Auto" Width="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</Grid>
Was it helpful?

Solution

This approach is a hack but can be used for the desired effect. Try putting an event handler on the Window.SizeChanged event to set the maxWidth of the first columndef. For example:

private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
     int borderBuffer = 9;
     //              AppWindow Size    Splitter Width     Far Column Min  FudgeFactor                
     Col0.MaxWidth = e.NewSize.Width - Col1.Width.Value - Col2.MinWidth - borderBuffer;
}

I needed to use this method to prevent a third party control in the top row of the grid from having some undesirable wrapping resulting from when the gridSplitter disregards the min/max width of the column with width set to "Auto". The borderBuffer may need to be adjusted for your case. The borderBuffer in my case didn't make perfect sense based on the geometry/column/border widths - it was just the magic number that worked for my layout.

If someone can come up with a cleaner solution, I'd love to use it instead. This solution reminds me of painfully trying to force VB6 to resize controls - yuck. But for now, it beats having items on the top row of my grid from getting hidden due to unexpected wrapping.

OTHER TIPS

I know this is a bit late, but I just run into this problem, and here is my solution. Unfortunately it is not general enough, it only works for a grid with two columns, but it can probably be adapted farther. However, it solves the described problem and my own, so here goes:

The solution consists in a hack or workaround, however you want to call it. Instead of declaring MinWidth for both the left and right column, you declare a MinWidth and a MaxWidth for the first column. This means that the GridSplitter won't move right of a defined location. So far, so good.

The next problem is that if we have a resizable container (the window in my case), this is not enough. It means that we cannot enlarge the left column as much as we want, even though there might be plenty of space for the second one. Fortunately, there is a solution: binding on the Grid ActualWidth and using an addition converter. The converter parameter will actually be the desired MinWidth for the right column, obviously the negative value, since we need to subtract it from the Grid Width. You could also use a SubtractConvertor, but that is up to you.

Here goes the xaml and code:

<Grid Background="{DynamicResource MainBackground}" x:Name="MainGrid" >
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="200" MinWidth="100" MaxWidth="{Binding Path=ActualWidth, RelativeSource={RelativeSource AncestorType=Grid}, Converter={Converters:AdditionConverter}, ConverterParameter=-250}" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <GridSplitter  Width="3" VerticalAlignment="Stretch" Grid.Column="0"/>
    <!-- your content goes here -->
</Grid>

and the converter:

[ValueConversion(typeof(double), typeof(double))]
public class AdditionConverter : MarkupExtension, IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        double dParameter;
        if (targetType != typeof(double) ||
            !double.TryParse((string)parameter, NumberStyles.Any, CultureInfo.InvariantCulture, out dParameter))
        {
            throw new InvalidOperationException("Value and parameter passed must be of type double");
        }
        var dValue = (double)value;
        return dValue + dParameter;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }

    #endregion

    #region Overrides of MarkupExtension

    /// <summary>
    /// When implemented in a derived class, returns an object that is set as the value of the target property for this markup extension. 
    /// </summary>
    /// <returns>
    /// The object value to set on the property where the extension is applied. 
    /// </returns>
    /// <param name="serviceProvider">Object that can provide services for the markup extension.
    ///                 </param>
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }

    #endregion
}

I hope this helps,

Mihai Drebot

I got this undesirable behaviour to stop by changing the * in the columndefinition to Auto and the 240 to *.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top