ScrollViewer is visible?
本文关键字:visible is ScrollViewer | 更新日期: 2023-09-27 18:14:42
我使用的是ComputedHorizontalScrollBarVisibility,但是当你将HorizontalScrollBarVisibility设置为"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 >
如果您需要控制ScrollViewer(或任何控件)的布局方式,请考虑使用ControlTemplate
,它可以在任何控件的Template
属性中访问。因为这将允许您绑定到对象本身和传递给它的值,并提供这样的模板。然而,这可能涉及到需要处理计算,以显示控件可见的确切部分。
你可以通过简单地将ScrollViewer
中的内容元素的宽度相加来得到你想要的,例如,如果你在ScrollViewer
中有StackPanel
(与Orientation=Horizontal
),那么将StackPanel
中的每个子元素的宽度相加,并将其与ScrollViewer
的ActualWidth
进行比较。如果总和小于ScrollViewer
的ActualWidth
,那么你需要滚动它。
详细信息请参考此链接
根据我的经验,滚动查看器属性值可能会过时,直到下一个布局通过。在我下面的简单示例中,它是代码隐藏的,但它确实按照你想要的方式工作。
我创建了一个名为"ShowScrollButtons"的依赖属性。你可以观察范围和视口大小的变化,并自动重新计算属性。
当滚动内容大小改变时,我触发对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 >
这在我的测试中效果很好。这是一个有趣的挑战。也许有人能给我们一个更好的方法,但我对此很满意。
感谢大家的回答,但最终得到了一个更容易的解决方案,而不是从StackPanel
的按钮绑定可见性,只是调用ScrollViewer
中的ScrollChanged
,然后在代码检查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;
}
}
}