2013-08-14 4 views
1

У меня есть Grid, который содержит три строки, а видимость третьей строки связана с булевым:GridSplitter отключает мой стиль RowDefinition

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="120"/> 
     <RowDefinition Height="*" /> 
     <RowDefinition> 
      <RowDefinition.Style> 
       <Style TargetType="{x:Type RowDefinition}"> 
        <Setter Property="Height" 
       Value="0.35*" /> 
        <Style.Triggers> 
         <DataTrigger Binding="{Binding ElementName=plotter2, Path=Visibility}" Value="Collapsed"> 
          <Setter Property="Height" Value="0" /> 
         </DataTrigger> 
        </Style.Triggers> 
       </Style> 
      </RowDefinition.Style> 
     </RowDefinition> 

У меня также есть GridSplitter:

<GridSplitter 
       ResizeDirection="Rows" 
       ResizeBehavior="BasedOnAlignment" 
       Grid.Column="0" 
       Grid.ColumnSpan="2" 
       Grid.Row="2"    
       Width="Auto" 
       Height="6" 
       HorizontalAlignment="Stretch" 
       VerticalAlignment="Top" 
       Margin="0 20 0 0" 
       Background="Transparent"/> 

Цель из этого является то, что когда я нажимаю Checkbox, последняя строка появляется и занимает 35% второй, но я могу изменить ее размер с помощью GridSplitter. Когда Checkbox не установлен, видимость строки - Collapsed.

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

У меня нет никакой идеи для этого, может ли кто-нибудь дать мне подсказку? Спасибо

ответ

4

Если вы используете DependencyPropertyHelper.GetValueSource (Rowdefinition.HeightProperty), вы можете видеть, что изначально значение свойства задается стилем, но после того, как GridSplitter изменит высоту строки, свойство height имеет «локальное» значение. Локальные значения имеют приоритет над всеми другими источниками для значения зависимости, поэтому, когда триггер данных пытается установить свойство height в 0, ничего не происходит.

В дополнение к этому, GridSplitter устанавливает высоту над ним над строкой, и как только будут задействованы относительные значения (звезды), набор высоты выглядит несколько недружелюбным.

Вот как я нашел, чтобы работать вокруг этой проблемы:

скрытие строки очистить значение свойства высоты, прежде чем пытаться установить высоту до 0

И

при отображении строки видно значение свойства высоты верхней строки для сброса высоты до ее начального значения.

Этот второй шаг вызвал у меня самую большую головную боль. Например, «недружественные» значения высоты, установленные GridSplitter, могут быть 181.7634545 *. Если вы хотите снова показать нижнюю строку, и вы дадите ей высоту 0,35 *, похоже, что она не становится видимой, так как она всего на пару пикселей высока!

К сожалению, я не нашел способ сделать это все в XAML. Решение полагается на программный сброс двух затронутых высот строк в соответствующий момент.

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

MainWindow.cs.xaml:

<Window x:Class="GridRowHidingSample.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" Height="350" Width="525"> 
<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="120" /> 
     <RowDefinition Name="TopRow" /> 
     <RowDefinition Name="BottomRow"> 
      <RowDefinition.Style> 
       <Style TargetType="{x:Type RowDefinition}"> 
        <Setter Property="Height" Value="0.35*" /> 
        <Style.Triggers> 
         <DataTrigger Binding="{Binding Path=IsRowVisible, Mode=OneWay}" Value="False"> 
          <Setter Property="Height" Value="0" /> 
         </DataTrigger> 
        </Style.Triggers> 
       </Style> 
      </RowDefinition.Style> 
     </RowDefinition> 
    </Grid.RowDefinitions> 
    <Border Background="Yellow"> 
     <CheckBox Content="Show bottom row" HorizontalAlignment="Left" VerticalAlignment="Top" IsChecked="{Binding Path=IsRowVisible, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="10" /> 
    </Border> 
    <Border Background="Red" Grid.Row="1"> 
    </Border> 
    <Border Grid.Row="2" Background="Green"> 
    </Border> 
    <GridSplitter Grid.Row="2" Height="10" HorizontalAlignment="Stretch" VerticalAlignment="Top" Background="DarkGray" Margin="0,20,0,0" /> 
</Grid> 

MainWindow.cs:

using System.Windows; 

namespace GridRowHidingSample 
{ 
    public partial class MainWindow : Window 
    { 
     private MainWindowViewModel _viewModel; 

     public MainWindow() 
     { 
      InitializeComponent(); 

      _viewModel = new MainWindowViewModel(TopRow, BottomRow); 
      DataContext = _viewModel; 
     } 
    } 
} 

И, наконец, модель. Важным битом является метод ResetHeight() и свойство IsRowVisible, где вызывается метод.

MainWindowViewModel.cs:

using System.ComponentModel; 
using System.Windows; 
using System.Windows.Controls; 

namespace GridRowHidingSample 
{ 
    public class MainWindowViewModel : INotifyPropertyChanged 
    { 
     private RowDefinition _topRow; 
     private RowDefinition _bottomRow; 
     private bool _isRowVisible = false; 

     public MainWindowViewModel(RowDefinition topRow, RowDefinition bottomRow) 
     { 
      _topRow = topRow; 
      _bottomRow = bottomRow; 
     } 

     private void ResetHeight(RowDefinition rowDefinition) 
     { 
      if (rowDefinition != null) 
      { 
       if (DependencyPropertyHelper.GetValueSource(rowDefinition, RowDefinition.HeightProperty).BaseValueSource == BaseValueSource.Local) 
       rowDefinition.ClearValue(RowDefinition.HeightProperty); 
      } 
     } 

     public bool IsRowVisible 
     { 
      get { return _isRowVisible; } 
      set 
      { 
       if (_isRowVisible != value) 
       { 
        _isRowVisible = value; 
        NotifyPropertyChanged("IsRowVisible"); 

        if (_isRowVisible) 
         ResetHeight(_topRow); 
        else 
         ResetHeight(_bottomRow); 
       } 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 

     protected void NotifyPropertyChanged(string propertyName) 
     { 
      var handler = PropertyChanged; 
      if (handler != null) 
       handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

Надеется, что это поможет вам, если вы еще не нашли другое решение.

+0

Спасибо за обмен – user1135594

Смежные вопросы