2013-02-19 107 views
0

我有一個WPF UserControl(在ElementHost之內),ScrollViewer包含ItemsControlHorizontalScrollbarVisibility設置爲Auto,所以如果不需要滾動,ScrollBar會被隱藏。WPF Scrollviewer當ScrollBar可見時,DesiredSize不會增加

我的要求是,如果ScrollBar顯示/隱藏,ElementHost會相應地調整它的高度。爲了實現這一點,我正在聽SizeChanged事件,我得到ScrollViewerDesiredSizeEventHandler,然後我通過DesiredSize.HeightElementHost

  1. visible 2.

的一種方式,其工作原理:隨着ScrollBar可見的(情況1),我擴大了我的窗前,直到ItemsControl的所有項目都可見,在ScrollBar消失, ElementHost適應高度降低(情況2)。 DesiredSize實際上在ScrollBar隱藏的時刻變小了。

另一種方式,但它不起作用:與ScrollBar不可見(情況2),我減少我的窗口大小,直到ScrollBar是必要的,並且出現。 DesiredSize保持不變,ElementHost不調整(情況3)。

任何想法?

這是Scrollviewer的XAML,一些MVVM的東西,不過不要讓她掛在這,點真的是,爲什麼DesiredSizeScrollBar出現在不增加嗎?爲什麼它只收縮?

<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Hidden" > 
    <i:Interaction.Behaviors> 
     <beh:HeightChangedBehavior HeightChangedCommand="{Binding HeightChangedCommand}" /> 
    </i:Interaction.Behaviors> 
    <ItemsControl ItemsSource="{Binding TabHeaders}" > 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <StackPanel IsItemsHost="True" Orientation="Horizontal"/> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate DataType="models:TabHeaderButtonModel"> 
       <RadioButton Content="{Binding Caption}" IsChecked="{Binding IsChecked, Mode=TwoWay}" GroupName="Tabs" 
          Command="{Binding SelectionChangedCommand}" CommandParameter="{Binding}" 
          Style="{StaticResource TabHeaderToggleButtonStyle}"> 
       </RadioButton> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 
</ScrollViewer> 

的ScrollViewer風格(基本上默認WPF):

<Style x:Key="ScrollViewerStyle1" TargetType="{x:Type ScrollViewer}"> 
    <Setter Property="Template" > 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type ScrollViewer}"> 
       <Grid x:Name="Grid" Background="{TemplateBinding Background}"> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="*"/> 
         <ColumnDefinition Width="Auto"/> 
        </Grid.ColumnDefinitions> 
        <Grid.RowDefinitions> 
         <RowDefinition Height="*"/> 
         <RowDefinition Height="Auto"/> 
        </Grid.RowDefinitions> 
        <Rectangle x:Name="Corner" Grid.Column="1" Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" Grid.Row="1"/> 
        <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" CanHorizontallyScroll="False" CanVerticallyScroll="False" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="0" Margin="{TemplateBinding Padding}" Grid.Row="0"/> 
        <ScrollBar x:Name="PART_VerticalScrollBar" AutomationProperties.AutomationId="VerticalScrollBar" Cursor="Arrow" Grid.Column="1" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Grid.Row="0" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}"/> 
        <ScrollBar x:Name="PART_HorizontalScrollBar" AutomationProperties.AutomationId="HorizontalScrollBar" Cursor="Arrow" Grid.Column="0" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Orientation="Horizontal" Grid.Row="1" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}" Style="{DynamicResource ScrollBarStyle1}"/> 
       </Grid> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
    <Style.Triggers> 
     <Trigger Property="IsEnabled" Value="false"> 
      <Setter Property="Foreground" Value="White"/> 
     </Trigger> 
    </Style.Triggers> 
</Style> 

回答

0

我不得不通過獲取ScrollViewer中的內容所需的高度和增加了滾動條的高度,如果可見,計算所需的高度。

這對我仍然感覺有點尷尬,所以如果你有更好的解決方案,我會很樂意改變接受的答案。

public class HeightChangedBehavior : Behavior<ScrollViewer> 
{ 
    public ICommand HeightChangedCommand { get { return (ICommand)GetValue(HeightChangedCommandProperty); } set { SetValue(HeightChangedCommandProperty, value); } } 
    public static readonly DependencyProperty HeightChangedCommandProperty = DependencyProperty.Register("HeightChangedCommand", typeof(ICommand), typeof(HeightChangedBehavior), new PropertyMetadata(null)); 


    protected override void OnAttached() 
    { 
     this.AssociatedObject.ScrollChanged += AssociatedObject_ScrollChanged; 
     base.OnAttached(); 
    } 

    /// <summary> 
    /// Calculates the desired height for the scrollviewer, as the sum of its content 
    /// desired height and, if visible, the horizontal scrollbar height. 
    /// </summary> 
    void AssociatedObject_ScrollChanged(object sender, ScrollChangedEventArgs e) 
    { 
     ScrollViewer sv = (ScrollViewer)sender; 

     // get content height 
     double height = ((FrameworkElement)sv.Content).DesiredSize.Height; 

     if (sv.ComputedHorizontalScrollBarVisibility == Visibility.Visible) 
     { 
      // add scrollbar height 
      height += (double)sv.FindResource(SystemParameters.HorizontalScrollBarHeightKey); // template of scrollbar should use this key 
     } 

     int intHeight = (int)Math.Ceiling(height); // whole pixels 

     // execute the command 
     ICommand cmd = this.HeightChangedCommand; 
     if (cmd != null && intHeight != sv.ActualHeight) 
      cmd.Execute(intHeight); 
    } 
} 
相關問題