我的解决方案是使用多值转换器,它以
ListBox
、
ScrollViewer
和层次结构中的
ListBoxItem
作为输入,还包括列表框
ActualHeight
、滚动查看器
VerticalOffset
和列表框项
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="">
<Button.Visibility>
<MultiBinding Converter="">
<Binding RelativeSource=""/>
<Binding RelativeSource=""/>
<Binding RelativeSource=""/>
<Binding Path="ActualHeight" RelativeSource=""/>
<Binding Path="VerticalOffset" RelativeSource=""/>
<Binding Path="ActualHeight" RelativeSource=""/>
</MultiBinding>
</Button.Visibility>
</Button>
</DataTemplate>