Нежелательное поведение разделителя сетки WPF - PullRequest
2 голосов
/ 13 апреля 2010

У меня есть простая сетка с 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 ]

3 голосов
/ 09 июня 2011

Я знаю, что это немного поздно, но я просто столкнулся с этой проблемой, и вот мое решение. К сожалению, он не является достаточно общим, он работает только для сетки с двумя столбцами, но, вероятно, его можно адаптировать дальше. Однако, это решает описанную проблему и мою собственную, так что здесь идет:

Решение состоит во взломе или обходном пути, однако вы хотите его назвать. Вместо того, чтобы объявлять 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
}

Надеюсь, это поможет,

Михай Дребот

2 голосов
/ 26 мая 2010

Этот подход взломан, но может быть использован для достижения желаемого эффекта. Попробуйте добавить обработчик события Window.SizeChanged, чтобы установить maxWidth первого столбцаdef. Например:

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 изменить размеры элементов управления. Но сейчас все равно, что элементы в верхнем ряду моей сетки скрыты из-за неожиданной упаковки.

1 голос
/ 13 апреля 2010

Я остановил это нежелательное поведение, изменив * в столбце с определением на Auto и 240 на *.

...