ScrollViewer可见吗?

时间:2014-07-24 14:55:40

标签: c# wpf xaml

我使用ComputedHorizo​​ntalScrollBarVisibility但是当您将Horizo​​ntalScrollBarVisibility设置为" Hidden"时,这不起作用。

我想要实现的目标是知道ScrollViewer是否应该可见而不显示ScrollViewer。然后绑定该结果以显示控制ScrollViewer的按钮(在本例中为下面的“StackPanel”)。

XAML

<ScrollViewer HorizontalScrollBarVisibility="Auto" x:Name="Scroll">
   .....
</ScrollViewer>
<StackPanel Visibility="{Binding ElementName=Scroll, Path=ComputedHorizontalScrollBarVisibility}">
   <Button Grid.Column="0" Content="Left" HorizontalAlignment="Left" Click="..."/>
   <Button Grid.Column="1" Content="Right" HorizontalAlignment="Right" Click="..."/>
</StackPanel >

4 个答案:

答案 0 :(得分:0)

如果您需要控制ScrollViewer(或任何控件,实际上)的布局方式,请考虑使用ControlTemplate,这可以在任何Control的Template属性中访问。因为这将允许您绑定到对象本身和传递给它的值,并提供这样的模板。但是,这可能涉及需要处理计算以显示可见的控件的确切部分。

答案 1 :(得分:0)

您可以通过简单地在ScrollViewer内添加内容元素的宽度来获得您想要的内容,例如如果StackPanel内有Orientation=HorizontalScrollViewer},请在StackPanel中加上每个子元素的宽度,并将其与ActualWidth的{​​{1}}进行比较{1}}。如果总和小于ScrollViewer的{​​{1}},则需要滚动它。

有关详细信息,请参阅此link

答案 2 :(得分:0)

根据我的经验,滚动查看器属性值可能是陈旧的,直到下一个布局传递。它在我下面的简单示例中代码隐藏,但这确实可以按照您想要的方式运行。

我创建一个名为&#34; ShowScrollButtons&#34;的依赖项属性。您可以观察范围和视口大小更改并自动重新计算属性。

当滚动内容大小发生变化时,我会触发重新评估ShowScrollButtons。请注意对UpdateLayout的调用,以确保范围和视口大小是最新的。同样,它是一个示例,所以我只在这里检查左/右滚动按钮的宽度

private void UpdateScrollButtonVis()
{
    UpdateLayout();
    ShowScrollButtons = (Scroll.ExtentHeight > Scroll.ViewportWidth);
}

在XAML ......

<Window.Resources>
    <BooleanToVisibilityConverter x:Key="boolvis"/>
</Window.Resources>
<Grid x:Name="theGrid">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="*"></RowDefinition>
        <RowDefinition Height="Auto"></RowDefinition>
    </Grid.RowDefinitions>
    <ScrollViewer Grid.Row="0"  Width="100" Height="100" VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Hidden" x:Name="Scroll">
        <Canvas x:Name="theCanvas"  Width="300" Height="300" Background="Green"/>
    </ScrollViewer>
    <StackPanel Grid.Row="1"  Visibility="{Binding ShowScrollButtons,Converter={StaticResource boolvis}}">
        <Button Grid.Column="0" Content="Left" HorizontalAlignment="Left" />
        <Button Grid.Column="1" Content="Right" HorizontalAlignment="Right" />
    </StackPanel >
    <Button x:Name="toggle" Grid.Row="2"  Height="25" Width="100" Click="toggle_Click">Toggle</Button>
</Grid>

<强>更新

新方法如何与多个滚动查看器和StackPanel一起使用,而无需代码隐藏。

使用附加属性来控制外部按钮可见性:

public class ScrollViewWatcher
{
    public static readonly DependencyProperty HorizontalButtonVisibility = DependencyProperty.RegisterAttached(
       "HorizontalButtonVisibility",
       typeof(Visibility),
       typeof(ScrollViewWatcher),
       new FrameworkPropertyMetadata(Visibility.Visible,
           FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure)
     );

    public static Visibility GetHorizontalButtonVisiblity(UIElement element)
    {
        return (Visibility)element.GetValue(HorizontalButtonVisibility);
    }

    public static void SetHorizontalButtonVisibility(UIElement element, Visibility value)
    {
        element.SetValue(HorizontalButtonVisibility, value);

        ScrollViewer sv = element as ScrollViewer;
        if (sv != null)
        {
            sv.ScrollChanged -= sv_ScrollChanged;
            sv.ScrollChanged += sv_ScrollChanged;
        }
    }

    static void sv_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        var sv = sender as ScrollViewer;
        if (sv != null)
        {
            var vis = sv.ExtentHeight > sv.ViewportWidth ? Visibility.Visible : Visibility.Hidden;
            sv.SetValue(HorizontalButtonVisibility, vis);
        }
    }
}

然后在XAML中,绑定到相应的ScrollViewer,如下所示:

<ScrollViewer 
    x:Name="sv1" local:ScrollViewWatcher.HorizontalButtonVisibility="Visible"  
    Grid.Row="0" Width="100" Height="100" VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Hidden" >
    <Canvas x:Name="theCanvas"  Width="300" Height="300" Background="Green"/>
</ScrollViewer>
<StackPanel Grid.Row="1" Visibility="{Binding ElementName=sv1,Path=(local:ScrollViewWatcher.HorizontalButtonVisibility), Mode=OneWay}">
        <Button Grid.Column="0" Content="Left" HorizontalAlignment="Left" />
    <Button Grid.Column="1" Content="Right" HorizontalAlignment="Right" />
</StackPanel >

这在我的测试中效果很好。这是一个有趣的挑战。也许有人可以用更好的方法来启发我们,但我对此非常满意。

答案 3 :(得分:0)

谢谢大家的答案,但最终得到的解决方法更容易,而不是绑定按钮的StackPanel的可见性,只需在ScrollChanged中调用ScrollViewer,然后在代码中检查ComputedHorizontalScrollBarVisibility并根据结果改变可见性。

XAML

<ScrollViewer HorizontalScrollBarVisibility="Auto" x:Name="Scroll" ScrollChanged="Scroll_ScrollChanged">
       .....
    </ScrollViewer>
    <StackPanel x:Name="BPanel" Visibility="Hidden">
       <Button Grid.Column="0" Content="Left" HorizontalAlignment="Left" Click="..."/>
       <Button Grid.Column="1" Content="Right" HorizontalAlignment="Right" Click="..."/>
    </StackPanel >

C#

private void Scroll_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
   ScrollViewer scroll = (ScrollViewer)sender;
   if(scroll.HorizontalScrollBarVisibility == ScrollBarVisibility.Auto)
   {
      if (scroll.ComputedHorizontalScrollBarVisibility == Visibility.Visible)
      {
         scroll.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden;
         BPanel.Visibility = Visibility.Visible;
      }
   }
}