2010-04-12 4 views
2

У меня простая сетка с тремя столбцами (одна из которых содержит разделитель сетки). При изменении размера сетки, а левая колонка достигает минимальной ширины, вместо того, чтобы ничего не делать, она увеличивает ширину правого столбца. Может ли кто-нибудь помочь мне остановить это?WPF нежелательное поведение разделителя сетки

Я не могу установить максимальную ширину правого столбца, так как сама сетка также изменяется.

Вот пример кода, который показывает проблему. В то время как изменение размера, переместить курсор на красную область:

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> 

ответ

2

Этот подход является взломом, но может быть использован для желаемого эффекта. Попробуйте помещать обработчик события в событие Window.SizeChanged, чтобы установить 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 в моем случае не имел никакого смысла, основываясь на ширине геометрии/столбца/границы - это было просто магическое число, которое работало для моего макета.

Если кто-то может придумать более чистое решение, я бы хотел использовать его вместо этого. Это решение напоминает мне о мучительной попытке заставить VB6 изменить размеры элементов управления - yuck. Но на данный момент это бьет, когда предметы в верхней строке моей сетки скрываются из-за неожиданной упаковки.

1

Я получил это нежелательное поведение, чтобы остановить путем изменения * в ColumnDefinition к Auto и 240 к *.

+0

Спасибо за Ваш ответ. Установка столбца в auto - это не поведение, которое я хочу для своей сетки. Любой из столбцов должен иметь *, заставляя его заполнять пространство. Авто не имеет такого поведения. – SaphuA

+0

Да, вы правы! Я экспериментировал еще немного, и на этот раз я нашел это по-настоящему, я думаю ... – Dabblernl

+0

Еще раз спасибо, но это тоже не работает :) Теперь я могу перетащить сплиттер на правую сторону. – SaphuA

2

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

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

Я надеюсь, что это помогает,

Михай ДРЕБОТА