我有一个帮助方法,用于确定控件在父容器中部分或完全可见。您可以使用它与Converter
一起使用来确定项目的可见性。
您的转换器需要从UI项计算父容器(如果您愿意,我的博客有一组Visual Tree Helpers可以帮助您完成这个任务),或者它可以是接受UI项和父容器作为参数的MultiConverter
。
ControlVisibility ctrlVisibility=
WPFHelpers.IsObjectVisibleInContainer(childControl, parentContainer);
if (ctrlVisibility == ControlVisibility.Full
|| isVisible == ControlVisibility.FullHeightPartialWidth)
{
return Visibility.Visible;
}
else
{
return = Visibility.Hidden;
}
确定控件在其父级中可见性的代码如下:
public enum ControlVisibility
{
Hidden,
Partial,
Full,
FullHeightPartialWidth,
FullWidthPartialHeight
}
public static ControlVisibility IsObjectVisibleInContainer(
FrameworkElement child, UIElement parent)
{
GeneralTransform childTransform = child.TransformToAncestor(parent);
Rect childSize = childTransform.TransformBounds(
new Rect(new Point(0, 0), new Point(child.ActualWidth, child.ActualHeight)));
Rect result = Rect.Intersect(
new Rect(new Point(0, 0), parent.RenderSize), childSize);
if (result == Rect.Empty)
{
return ControlVisibility.Hidden;
}
if (Math.Round(result.Height, 2) == childSize.Height
&& Math.Round(result.Width, 2) == childSize.Width)
{
return ControlVisibility.Full;
}
if (result.Height == childSize.Height)
{
return ControlVisibility.FullHeightPartialWidth;
}
if (result.Width == childSize.Width)
{
return ControlVisibility.FullWidthPartialHeight;
}
return ControlVisibility.Partial;
}
编辑
进行了一些测试,显然转换器在控件实际呈现之前就已经运行。作为一种hack方法,如果您使用MultiConverter
并将其传递给控件的ActualHeight
,则会在控件呈现时强制重新评估转换器,这样它就可以正常工作。
以下是我使用的转换器:
public class TestConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
FrameworkElement child = values[0] as FrameworkElement;
var parent = VisualTreeHelpers.FindAncestor<ListBox>(child);
ControlVisibility ctrlVisibility =
VisualTreeHelpers.IsObjectVisibleInContainer(child, parent);
if (ctrlVisibility == ControlVisibility.Full
|| ctrlVisibility == ControlVisibility.FullHeightPartialWidth)
{
return Visibility.Visible;
}
else
{
return Visibility.Hidden;
}
}
public object[] ConvertBack(object value, Type[] targetType, object parameter, CultureInfo culture)
{
return null;
}
}
我使用了你在问题中发布的XAML代码,并在.Resources
中添加了一个ListBoxItem
的隐式样式。
<ListBox.Resources>
<Style TargetType="">
<Setter Property="Visibility">
<Setter.Value>
<MultiBinding Converter="">
<Binding RelativeSource="" />
<Binding RelativeSource="" Path="ActualHeight" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</ListBox.Resources>
VirtualizingPanel.ScrollUnit
的设置?因为默认情况下它被设置为Item
,这正是你要寻找的。也许可以发布一些代码和截图,由于这是开发者预览版,如果确实是一个 bug,你可以提交一个故障工单到 Microsoft Connect? - myermianScrollUnit
设置为Item
。我将编辑并添加我的示例代码。 - Josh G