2010-10-19 5 views
13

Я хочу, чтобы макет сетки с двумя рядами и разделителем между ними. Строки должны иметь минимальную высоту 80 пикселей.GridSplitter с минимальными ограничениями

Этот код прекрасно работает:

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="*" MinHeight="80" /> 
     <RowDefinition Height="5" /> 
     <RowDefinition Height="*" MinHeight="80" /> 
    </Grid.RowDefinitions> 
    <TextBlock Grid.Row="0" Text="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}" /> 
    <GridSplitter Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="Red" /> 
    <TextBlock Grid.Row="2" Text="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}" /> 
</Grid> 

Но я хочу, верхний ряд, чтобы иметь автоматическую высоту, пока пользователь вручную не изменить его с помощью разветвителя. Поэтому я изменил код:

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto" MinHeight="80" /> 
     <RowDefinition Height="5" /> 
     <RowDefinition Height="*" MinHeight="80" /> 
    </Grid.RowDefinitions> 
    <TextBlock Grid.Row="0" Text="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}" /> 
    <GridSplitter Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="Red" /> 
    <TextBlock Grid.Row="2" Text="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}" /> 
</Grid> 

И есть проблема. Splitter все еще удовлетворяет ограничениям строк, но он бесконечно увеличивает высоту верхней строки, если я слишком сильно перетаскиваю сплиттер. Это приведет к тому, что нижняя строка будет полностью ниже нижней границы окна.

Я сделал некоторый рефлектор на коде GridSplitter и вижу, что он использует другую логику, если строки имеют Auto или Star height.

Любые предложения, как я могу «исправить» это?

ответ

5

Я разработал обходной путь для решения этой проблемы. Точка - установить MaxHeight для верхней строки, пока мы перетаскиваем разделитель. Здесь код:

public class FixedGridSplitter : GridSplitter 
{ 
    private Grid grid; 
    private RowDefinition definition1; 
    private double savedMaxLength; 

    #region static 

    static FixedGridSplitter() 
    { 
     new GridSplitter(); 
     EventManager.RegisterClassHandler(typeof(FixedGridSplitter), Thumb.DragCompletedEvent, new DragCompletedEventHandler(FixedGridSplitter.OnDragCompleted)); 
     EventManager.RegisterClassHandler(typeof(FixedGridSplitter), Thumb.DragStartedEvent, new DragStartedEventHandler(FixedGridSplitter.OnDragStarted)); 
    } 

    private static void OnDragStarted(object sender, DragStartedEventArgs e) 
    { 
     FixedGridSplitter splitter = (FixedGridSplitter)sender; 
     splitter.OnDragStarted(e); 
    } 

    private static void OnDragCompleted(object sender, DragCompletedEventArgs e) 
    { 
     FixedGridSplitter splitter = (FixedGridSplitter)sender; 
     splitter.OnDragCompleted(e); 
    } 

    #endregion 

    private void OnDragStarted(DragStartedEventArgs sender) 
    {    
     grid = Parent as Grid; 
     if (grid == null) 
      return;    
     int splitterIndex = (int)GetValue(Grid.RowProperty); 
     definition1 = grid.RowDefinitions[splitterIndex - 1]; 
     RowDefinition definition2 = grid.RowDefinitions[splitterIndex + 1]; 
     savedMaxLength = definition1.MaxHeight;    

     double maxHeight = definition1.ActualHeight + definition2.ActualHeight - definition2.MinHeight;    
     definition1.MaxHeight = maxHeight; 
    } 

    private void OnDragCompleted(DragCompletedEventArgs sender) 
    { 
     definition1.MaxHeight = savedMaxLength; 
     grid = null; 
     definition1 = null; 
    } 
} 

Затем просто замените GridSplitter на FixedGridSplitter.

Примечание: этот код не является общим - он не поддерживает столбцы и предполагает, что нижняя строка указана в MinHeight.

5

Я столкнулся с этой проблемой несколько раз сам. Кажется, что GridSplitter не очень хорошо работает с Auto. Тем не менее, я нашел потенциальное обходное решение.

Вы можете указать значение объекта GridLength, используя «звездные коэффициенты». Это действует как множитель для рассматриваемой длины.

В вашем примере, если вы берете строку, которую хотите сохранить как звезда, и установите коэффициент звезды на действительно большое количество, строка займет все свободное пространство (заставляя другую строку становиться ее мини- высота). Хотя это не то же поведение, что и «auto» (высота первой строки не определяется ее высотой содержимого), это может приблизиться к вам.

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="*" MinHeight="80" /> 
     <RowDefinition Height="5" /> 
     <RowDefinition Height="10000*" MinHeight="80" /> 
    </Grid.RowDefinitions> 
    <TextBlock Grid.Row="0" Text="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}" /> 
    <GridSplitter Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="Red" /> 
    <TextBlock Grid.Row="2" Text="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}" /> 
</Grid> 
+0

Благодарим вас, но я хочу сохранить авто логику – Seldon

+0

Это работало блестяще для меня, теперь калибровка работает отлично. – Contango