컨트롤이 부분적으로 또는 완전히 부모 컨테이너 내에서 볼 수 있는지를 결정하는 데 사용하는 도우미 메서드가 있습니다. 항목의 가시성을 확인하려면 Converter
과 함께 사용하면됩니다.
변환기는 UI 항목에서 상위 컨테이너를 계산해야합니다 (원할 경우 내 블로그에 도움이되는 Visual Tree Helpers 세트가 있음). UI 항목과 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
}
/// <summary>
/// Checks to see if an object is rendered visible within a parent container
/// </summary>
/// <param name="child">UI element of child object</param>
/// <param name="parent">UI Element of parent object</param>
/// <returns>ControlVisibility Enum</returns>
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;
}
편집
는 몇 가지 테스트를하고 컨트롤이 실제로 렌더링되기 전에 분명히 컨버터가 실행됩니다. 해킹으로 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
<ListBox.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Visibility">
<Setter.Value>
<MultiBinding Converter="{StaticResource Converter}">
<Binding RelativeSource="{RelativeSource Self}" />
<Binding RelativeSource="{RelativeSource Self}" Path="ActualHeight" />
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</ListBox.Resources>
에
ListBoxItem
에 대한 암시 적 스타일을 추가 VirtualizingPanel.ScrollUnit'이 (가)로 설정되어 있습니까? 왜냐하면, 기본값으로'Item'으로 설정되어 있기 때문에 당신이 찾고있는 것입니다. 아마 일부 코드와 스크린 샷을 게시 할 것입니다. 개발자 시연이므로 진정한 버그 일 경우 Microsoft Connect에 문제 티켓을 제출할 수 있습니까? –'ScrollUnit'을 명시 적으로'Item'으로 설정하고 있습니다. 샘플 코드를 편집하고 추가하겠습니다. –
내가 아는 바로는 이것이 가상화의 "특징"입니다. 속도면에서 디스플레이 컨테이너를 다시 사용할 때 너비를 재평가하지 않습니다. 당신은 horizontalcontent alignment = stretch를 시도 할 수 있습니다.또는 문자열 목록을 반복하고 명시 적으로 최대 너비를 수용하도록 너비를 설정할 수 있습니다. 또는 가장 많이 처리 할 것으로 생각되는 고정 너비를 설정하고 텍스트 줄 바꿈을 사용할 수 있습니다. – Paparazzi