WPF不需要的网格分割器行为

时间:2010-04-12 21:09:34

标签: wpf resize width max gridsplitter

我有一个简单的网格,有3列(其中一列包含一个网格分割器)。调整网格大小并且左列达到其最小宽度时,不会执行任何操作,而是增加右列的宽度。谁能帮助我阻止这个?

我无法设置右列的最大宽度,因为网格本身也会调整大小。

以下是一些显示问题的示例代码。调整大小时,将鼠标移到红色区域上:

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>

3 个答案:

答案 0 :(得分:3)

我知道这有点晚了,但我遇到了这个问题,这是我的解决方案。不幸的是,它不够通用,它只适用于有两列的网格,但它可能可以进一步调整。但是,它解决了所描述的问题和我自己的问题,所以这里是:

解决方案包括黑客或解决方法,但您想要调用它。您不是为左列和右列声明MinWidth,而是为第一列声明MinWidth和MaxWidth。这意味着GridSplitter不会移动到定义的位置。到现在为止还挺好。

下一个问题是,如果我们有一个可调整大小的容器(在我的情况下是窗口),这还不够。这意味着我们不能尽可能多地放大左列,即使第二个可能有足够的空间。幸运的是,有一个解决方案:绑定Grid ActualWidth并使用加法转换器。转换器参数实际上是右列所需的MinWidth,显然是负值,因为我们需要从网格宽度中减去它。您也可以使用SubtractConvertor,但这取决于您。

这里是xaml和代码:

<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>

和转换器:

[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
}

我希望这有帮助,

Mihai Drebot

答案 1 :(得分:2)

这种方法是一种破解,但可以用于所需的效果。尝试在Window.SizeChanged事件上放置一个事件处理程序来设置第一个columndef的maxWidth。例如:

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;
}

我需要使用此方法来防止网格顶行中的第三方控件因gridSplitter忽略宽度设置为“Auto”的列的最小/最大宽度而产生一些不合需要的包装。可能需要根据您的情况调整borderBuffer。在我的情况下,borderBuffer根据几何/列/边框宽度没有完美的意义 - 它只是对我的布局起作用的神奇数字。

如果有人能提出更清洁的解决方案,我很乐意使用它。这个解决方案让我想起了痛苦地试图强制VB6调整控件的大小 - 哎呀。但就目前而言,由于意外包装,我的网格顶行上的项目会被隐藏起来。

答案 2 :(得分:1)

我通过将列定义中的*更改为Auto而将240更改为*来解决此不良行为。