【问题标题】:WPF unwanted grid splitter behaviourWPF 不需要的网格拆分器行为
【发布时间】:2011-02-07 04:52:21
【问题描述】:

我有一个包含 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>

【问题讨论】:

    标签: wpf resize width max gridsplitter


    【解决方案1】:

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

    解决方案包含黑客或解决方法,但是您想调用它。不是为左列和右列都声明 MinWidth,而是为第一列声明 MinWidth 和 MaxWidth。这意味着 GridSplitter 不会向右移动定义的位置。到目前为止,一切都很好。

    下一个问题是,如果我们有一个可调整大小的容器(在我的例子中是窗口),这还不够。这意味着我们不能随心所欲地扩大左列,即使第二列可能有足够的空间。幸运的是,有一个解决方案:绑定 Grid ActualWidth 并使用加法转换器。转换器参数实际上是右列所需的 MinWidth,显然是负值,因为我们需要从 Grid Width 中减去它。您也可以使用 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
    }
    

    希望对你有帮助,

    米海Drebot

    【讨论】:

      【解决方案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 忽略宽度设置为“自动”的列的最小/最大宽度时产生一些不希望的换行。可能需要根据您的情况调整borderBuffer。根据几何/列/边框宽度,在我的例子中,borderBuffer 并没有完全的意义——它只是对我的布局有用的幻数。

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

      【讨论】:

        【解决方案3】:

        通过将列定义中的 * 更改为 Auto 并将 240 更改为 *,我停止了这种不良行为。

        【讨论】:

        • 感谢您的回复。将列设置为 auto 不是我想要的网格行为。任何一列都应该有 *,使它填满空间。 Auto 没有这种行为。
        • 是的,你是对的!我尝试了更多,这次我发现它是真实的,我认为......
        • 再次感谢,但这也不起作用 :) 我现在可以将拆分器拖出右侧。
        猜你喜欢
        • 1970-01-01
        • 2010-12-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-16
        • 1970-01-01
        相关资源
        最近更新 更多