我的解决方案是使用一个多值转换器,它将层次结构中的ListBox、ScrollViewer 和ListBoxItem 以及列表框ActualHeight、滚动查看器@ 作为输入987654325@ 和列表框项ActualHeight 并返回可见性。树的最后一个(双精度)值仅用于确保转换器的 Convert 方法将在任何重大值更改时被调用。基本上,如果项目的底部大于滚动查看器的底部,则返回的Visibility 为Hidden,否则返回Visible。
这是转换器的代码:
using System;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
public class ListBoxItemToVisibilityConverter : IMultiValueConverter
{
public object Convert(
object[] values,
Type targetType,
object parameter,
CultureInfo culture)
{
if ((values?.Length ?? 0) != 6)
return Visibility.Collapsed;
var listBox = values.OfType<ListBox>().FirstOrDefault();
var scrollViewer = values.OfType<ScrollViewer>().FirstOrDefault();
var listBoxItem = values.OfType<ListBoxItem>().FirstOrDefault();
var heights = values.OfType<double>().ToArray();
if (new object[] { listBox, scrollViewer, listBoxItem }.Any(item => item == null) || heights.Length != 3)
return Visibility.Collapsed;
var scrollViewerBottom = scrollViewer.PointToScreen(new Point(0, scrollViewer.ActualHeight)).Y;
var listBoxItemBottom = listBoxItem.PointToScreen(new Point(0, listBoxItem.ActualHeight)).Y;
return listBoxItemBottom > scrollViewerBottom ? Visibility.Hidden : Visibility.Visible;
}
public object[] ConvertBack(
object value,
Type[] targetTypes,
object parameter,
CultureInfo culture) =>
throw new NotSupportedException();
}
它的声明:
<local:ListBoxItemToVisibilityConverter x:Key="ListBoxItemToVisibility"/>
它在项目模板中的用法:
<DataTemplate>
<Button Content="{Binding Text}">
<Button.Visibility>
<MultiBinding Converter="{StaticResource ListBoxItemToVisibility}">
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType=ListBoxItem}"/>
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType=ScrollViewer}"/>
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType=ListBox}"/>
<Binding Path="ActualHeight" RelativeSource="{RelativeSource FindAncestor, AncestorType=ListBoxItem}"/>
<Binding Path="VerticalOffset" RelativeSource="{RelativeSource FindAncestor, AncestorType=ScrollViewer}"/>
<Binding Path="ActualHeight" RelativeSource="{RelativeSource FindAncestor, AncestorType=ListBox}"/>
</MultiBinding>
</Button.Visibility>
</Button>
</DataTemplate>