WPF - 滚动 ScrollViewer 时设置图像可见性
WPF - Set image visibility when ScrollViewer is scrolled
我在 WPF 用户控件上有一个 ScrollViewer
,我想要实现的是在 ScrollViewer
的顶部和底部显示阴影图像,但隐藏顶部阴影当滚动条在顶部时隐藏底部阴影
换句话说,我需要以某种方式将图像的 Visibility
属性 绑定到 ScrollViewer
的偏移量。以下代码显然不正确,但应该说明我正在尝试做什么。
<Grid>
<Image Source="Shadow.png" VerticalAlignment="Top">
<Image.Resources>
<Style TargetType="Image">
<Style.Triggers>
<Trigger SourceName="Scroller" Property="VerticalOffset" Value="GREATER THAN ZERO OR LESS THAN MAX">
<Setter Property="Visibility" Value="Collapsed" />
</Trigger>
</Style.Triggers>
</Style>
</Image.Resources>
</Image>
<ScrollViewer Height="200" x:Name="Scroller">
<ContentControl />
</ScrollViewer>
</Grid>
您必须使用 ScrollBar
而不是 ScrollViewer
,因为 ScrollViewer
无法判断它何时到达其内容的末尾。 (或者至少我还没有看到这样做的可靠方法)。另一方面 ScrollBar
更适合这类操作。
我使用包含多个项目的列表框来测试此行为。你可以把它改成任何你需要的。
Xaml :
<Grid>
<ListBox ScrollBar.Scroll="ListBox_Scroll">
<!-- add many items here -->
<TextBlock Text="something"/>
</ListBox>
<Image Source="Shadow.png" VerticalAlignment="Top">
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<DataTrigger Binding="{Binding ScrollerState}"
Value="{x:Static enum:ScrollState.AtTheTop}">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<Image Source="Shadow.png" VerticalAlignment="Bottom">
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<DataTrigger Binding="{Binding ScrollerState}"
Value="{x:Static enum:ScrollState.AtTheBottom}">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Grid>
如您所见,我将触发器更改为 DataTrigger
并在 DataContext 中使用了可绑定的 属性(名为 ScrollerState
,类型为 ScrollState
,这是一个简单的枚举) 绑定到。
枚举:
public enum ScrollState
{
AtTheTop, AtTheBottom, InBetween
}
现在在代码隐藏中,我们从更改 ScrollerState
:
的值的地方实现 Scroll 事件
public MainWindow()
{
InitializeComponent();
DataContext = new VM();
}
private void ListBox_Scroll(object sender, ScrollEventArgs e)
{
ScrollBar sb = e.OriginalSource as ScrollBar;
if (sb.Orientation == Orientation.Horizontal)
return;
if (sb.Value == 0)
(DataContext as VM).ScrollerState = ScrollState.AtTheTop;
else if (sb.Value == sb.Maximum)
(DataContext as VM).ScrollerState = ScrollState.AtTheBottom;
else
(DataContext as VM).ScrollerState = ScrollState.InBetween;
}
VM(此实例设置为 window 的 DataContext):
public class VM : DependencyObject
{
public ScrollState ScrollerState
{
get { return (ScrollState)GetValue(ScrollerStateProperty); }
set { SetValue(ScrollerStateProperty, value); }
}
public static readonly DependencyProperty ScrollerStateProperty =
DependencyProperty.Register("ScrollerState", typeof(ScrollState), typeof(VM),
new PropertyMetadata(ScrollState.AtTheTop));
}
这是我会做的:
首先,您需要一个 IMultiValueConverter:
public class ScrollOffsetToVisibilityConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values == null)
throw new ArgumentException("Values cannot be null.");
if (values.Count() != 2)
throw new ArgumentException("Incorrect number of bindings (" + values.Count() + ")");
if (parameter == null)
throw new ArgumentException("Parameter cannot be null.");
var top = parameter.ToString().ToUpper() == "TOP";
var offset = Double.Parse(values[0].ToString());
var maxHeight = Double.Parse(values[1].ToString());
return (top && offset == 0) || (!top && offset == maxHeight) ? Visibility.Visible : Visibility.Collapsed;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
然后,您可以使用此转换器为图像的可见度 属性 应用 Setter。
<Image.Style Source="Shadow.png" VerticalAlignment="Top">
<Style>
<Setter Property="Image.Visibility">
<Setter.Value>
<MultiBinding Converter="{StaticResource ScrollOffsetToVisibilityConverter}" ConverterParameter="Top">
<Binding ElementName="Scroller" Path="VerticalOffset"/>
<Binding ElementName="Scroller" Path="ScrollableHeight"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</Image.Style>
如果滚动条是在顶部或底部。
我在 WPF 用户控件上有一个 ScrollViewer
,我想要实现的是在 ScrollViewer
的顶部和底部显示阴影图像,但隐藏顶部阴影当滚动条在顶部时隐藏底部阴影
换句话说,我需要以某种方式将图像的 Visibility
属性 绑定到 ScrollViewer
的偏移量。以下代码显然不正确,但应该说明我正在尝试做什么。
<Grid>
<Image Source="Shadow.png" VerticalAlignment="Top">
<Image.Resources>
<Style TargetType="Image">
<Style.Triggers>
<Trigger SourceName="Scroller" Property="VerticalOffset" Value="GREATER THAN ZERO OR LESS THAN MAX">
<Setter Property="Visibility" Value="Collapsed" />
</Trigger>
</Style.Triggers>
</Style>
</Image.Resources>
</Image>
<ScrollViewer Height="200" x:Name="Scroller">
<ContentControl />
</ScrollViewer>
</Grid>
您必须使用 ScrollBar
而不是 ScrollViewer
,因为 ScrollViewer
无法判断它何时到达其内容的末尾。 (或者至少我还没有看到这样做的可靠方法)。另一方面 ScrollBar
更适合这类操作。
我使用包含多个项目的列表框来测试此行为。你可以把它改成任何你需要的。
Xaml :
<Grid>
<ListBox ScrollBar.Scroll="ListBox_Scroll">
<!-- add many items here -->
<TextBlock Text="something"/>
</ListBox>
<Image Source="Shadow.png" VerticalAlignment="Top">
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<DataTrigger Binding="{Binding ScrollerState}"
Value="{x:Static enum:ScrollState.AtTheTop}">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<Image Source="Shadow.png" VerticalAlignment="Bottom">
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<DataTrigger Binding="{Binding ScrollerState}"
Value="{x:Static enum:ScrollState.AtTheBottom}">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Grid>
如您所见,我将触发器更改为 DataTrigger
并在 DataContext 中使用了可绑定的 属性(名为 ScrollerState
,类型为 ScrollState
,这是一个简单的枚举) 绑定到。
枚举:
public enum ScrollState
{
AtTheTop, AtTheBottom, InBetween
}
现在在代码隐藏中,我们从更改 ScrollerState
:
public MainWindow()
{
InitializeComponent();
DataContext = new VM();
}
private void ListBox_Scroll(object sender, ScrollEventArgs e)
{
ScrollBar sb = e.OriginalSource as ScrollBar;
if (sb.Orientation == Orientation.Horizontal)
return;
if (sb.Value == 0)
(DataContext as VM).ScrollerState = ScrollState.AtTheTop;
else if (sb.Value == sb.Maximum)
(DataContext as VM).ScrollerState = ScrollState.AtTheBottom;
else
(DataContext as VM).ScrollerState = ScrollState.InBetween;
}
VM(此实例设置为 window 的 DataContext):
public class VM : DependencyObject
{
public ScrollState ScrollerState
{
get { return (ScrollState)GetValue(ScrollerStateProperty); }
set { SetValue(ScrollerStateProperty, value); }
}
public static readonly DependencyProperty ScrollerStateProperty =
DependencyProperty.Register("ScrollerState", typeof(ScrollState), typeof(VM),
new PropertyMetadata(ScrollState.AtTheTop));
}
这是我会做的:
首先,您需要一个 IMultiValueConverter:
public class ScrollOffsetToVisibilityConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values == null)
throw new ArgumentException("Values cannot be null.");
if (values.Count() != 2)
throw new ArgumentException("Incorrect number of bindings (" + values.Count() + ")");
if (parameter == null)
throw new ArgumentException("Parameter cannot be null.");
var top = parameter.ToString().ToUpper() == "TOP";
var offset = Double.Parse(values[0].ToString());
var maxHeight = Double.Parse(values[1].ToString());
return (top && offset == 0) || (!top && offset == maxHeight) ? Visibility.Visible : Visibility.Collapsed;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
然后,您可以使用此转换器为图像的可见度 属性 应用 Setter。
<Image.Style Source="Shadow.png" VerticalAlignment="Top">
<Style>
<Setter Property="Image.Visibility">
<Setter.Value>
<MultiBinding Converter="{StaticResource ScrollOffsetToVisibilityConverter}" ConverterParameter="Top">
<Binding ElementName="Scroller" Path="VerticalOffset"/>
<Binding ElementName="Scroller" Path="ScrollableHeight"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</Image.Style>
如果滚动条是在顶部或底部。