2013-02-19 15 views
0

ScrollViewerItemsControl이 포함 된 WPF UserControl (ElementHost 내부)이 있습니다. HorizontalScrollbarVisibilityAuto으로 설정되므로 스크롤이 필요하지 않으면 ScrollBar이 숨겨집니다.WPF Scrollviewer ScrollBar가 표시 될 때 DesiredSize가 증가하지 않습니다.

ScrollBar이 표시되거나 숨겨지면 ElementHost은 그에 따라 높이를 조정한다는 것이 나의 요구 사항입니다. 이를 달성하기 위해 나는 SizeChanged 이벤트를 듣고 EventHandlerScrollViewerDesiredSize을 얻은 다음 을 ElementHost에 전달합니다.

  1. visible 2. hidden 3. incorrect, overlaid

한 가지 방법은,이 작품 다음 ItemsControl의 모든 항목이 표시 될 때까지 ScrollBar 볼 (상황 1)으로, 내 창을 확대의 ScrollBar가 사라지고, ElementHost은 감소 된 높이로 조정됩니다 (상황 2). DesiredSize 실제로는 ScrollBar이 숨겨져있는 순간이 작아졌습니다.

다른 방법으로는 작동하지 않습니다. ScrollBar이 보이지 않으면 (상황 2), ScrollBar이 필요하고 나타날 때까지 창 크기를 줄입니다. DesiredSize은 동일하게 유지되고 ElementHost은 조정되지 않습니다 (상황 3).

아이디어가 있으십니까? DesiredSize이 때 ScrollBar 나타납니다 증가하지

이 일부 MVVM 물건과 함께 Scrollviewer의 XAML이지만, 정말이며,이에 지점을 끊었되지 않는 이유는 무엇입니까? 왜 그것은 단지 수축입니까? (기본적으로 WPF 기본)

<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 스타일 :

<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); 
    } 
}