当ScrollBar变为可见时,WPF Scrollviewer DesiredSize不会增加 [英] WPF Scrollviewer DesiredSize does not increase when ScrollBar gets Visible

查看:111
本文介绍了当ScrollBar变为可见时,WPF Scrollviewer DesiredSize不会增加的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个WPF UserControl(在ElementHost内部),其中的ScrollViewer包含ItemsControl. HorizontalScrollbarVisibility设置为Auto,因此如果不需要滚动,则ScrollBar会被隐藏.

I have a WPF UserControl (inside an ElementHost) with a ScrollViewer that contains an ItemsControl . The HorizontalScrollbarVisibility is set to Auto, so if no scrolling is necessary, the ScrollBargets hidden.

我的要求是,如果ScrollBar被显示/隐藏,ElementHost会相应地调整其高度.为此,我正在监听SizeChanged事件,在EventHandler中获得ScrollViewerDesiredSize,然后将DesiredSize.Height传递给ElementHost.

My requirement is, that if the ScrollBar gets shown/hidden, the ElementHost does adjust it's height accordingly. To achieve that, I'm listening to the SizeChanged event, I get the DesiredSize of the ScrollViewer in the EventHandler, then I pass DesiredSize.Height to the ElementHost.

  1. 2. 3.

一种方法,它起作用:在ScrollBar可见的情况下(情况1),我扩大窗口,直到ItemsControl的所有项目都可见,ScrollBar消失,ElementHost调整为减小的高度(情况) 2). ScrollBar隐藏后,DesiredSize实际上变小了.

One way, this works: With ScrollBar visible (situation 1), I enlarge my window until all items of the ItemsControl are visible, the ScrollBar disappears, the ElementHost adjusts to reduced height (situation 2). DesiredSize actually got smaller the moment the ScrollBar is hidden.

但是,另一种方法却行不通:在ScrollBar不可见的情况下(情况2),我减小了窗口的大小,直到需要ScrollBar并出现为止. DesiredSize保持不变,并且ElementHost不会调整(情况3).

The other way, though, it doesn't work: With ScrollBar not visible (situation 2), I reduce my window size until a ScrollBar is necessary and appears. DesiredSize stays the same, and the ElementHost does not adjust (situation 3).

有什么想法吗?

这是Scrollviewer的xaml,其中包含一些MVVM内容,但是请不要挂在嘴上,实际上是,为什么当ScrollBar出现时,为什么DesiredSize没有增加?为什么只收缩?

This is the xaml of the Scrollviewer, with some MVVM stuff, but don't get hung up on this, the point really is, why does the DesiredSize not increase when the ScrollBar appears? Why is it shrink only?

<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):

ScrollViewer style (basically default 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>

推荐答案

我必须通过获取ScrollViewer的内容所需的高度并添加ScrollBar高度(如果可见)来计算所需的高度.

I had to calculate the desired height by getting the ScrollViewer's content desired height and adding the ScrollBar height if visible.

这对我来说仍然有点尴尬,因此,如果您有更好的解决方案,我会很乐意更改接受的答案.

This still feels slightly awkward to me, so if you have a better solution, I'll gladly change the accepted answer.

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

这篇关于当ScrollBar变为可见时,WPF Scrollviewer DesiredSize不会增加的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆