5

따라서 스크롤 영역의 끝에서 항목이 잘 리거나 잘리는 경우 크롬이없는 모음이있는 것은 정말 바보입니다.항목을 자르지 않는 가상화 패널

전체 항목 만 그리는 항목이 아니라 항목의 항목 만 그리는 모음 (ItemsControl/ListBox)의 가상화 패널을 만들고 싶습니다. 예를 들어 :

______________ 
|    | 
|______________| 
______________ 
|    | 
|______________| 
______________ 
|    | 

enter image description here

나는 전체 항목/컨테이너가 표시 될 여지가없는 제 3 부분 컨테이너가 표시되고 싶지 않아. 예에서 공간 부족으로 세 번째 항목이 잘립니다.

제안 사항? 바퀴를 재발견해야합니까 (내 자신을 구축하십시오 VirtualizingWholeItemPanel)?

편집 :

Microsoft는 VirtualizingPanel.ScrollUnit이 모두이 기능을 수행하도록 구성되지 않는다는 것을 명확히. VirtualizingPanel.ScrollUnitCanContentScroll과 매우 유사한 목적을 가지고 있습니다 (ScrollViewer).

+0

ListBoxItem에 대한 암시 적 스타일을 추가 VirtualizingPanel.ScrollUnit'이 (가)로 설정되어 있습니까? 왜냐하면, 기본값으로'Item'으로 설정되어 있기 때문에 당신이 찾고있는 것입니다. 아마 일부 코드와 스크린 샷을 게시 할 것입니다. 개발자 시연이므로 진정한 버그 일 경우 Microsoft Connect에 문제 티켓을 제출할 수 있습니까? –

+0

'ScrollUnit'을 명시 적으로'Item'으로 설정하고 있습니다. 샘플 코드를 편집하고 추가하겠습니다. –

+0

내가 아는 바로는 이것이 가상화의 "특징"입니다. 속도면에서 디스플레이 컨테이너를 다시 사용할 때 너비를 재평가하지 않습니다. 당신은 horizontalcontent alignment = stretch를 시도 할 수 있습니다.또는 문자열 목록을 반복하고 명시 적으로 최대 너비를 수용하도록 너비를 설정할 수 있습니다. 또는 가장 많이 처리 할 것으로 생각되는 고정 너비를 설정하고 텍스트 줄 바꿈을 사용할 수 있습니다. – Paparazzi

답변

4

컨트롤이 부분적으로 또는 완전히 부모 컨테이너 내에서 볼 수 있는지를 결정하는 데 사용하는 도우미 메서드가 있습니다. 항목의 가시성을 확인하려면 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> 
+0

ControlVisibility는'[Flags]'열거 형으로 바뀔 수 있습니다. 게임 변화는 없지만 단지 제안. –

+0

좋은 게시글. 고맙습니다! –

+1

@ m-y : 깃발 열거로 만들 이유가 없을 것이라고 생각합니다. 값은 둘 이상의 가능성과 같아서는 안됩니다. 내 이해 플래그에서 enum은 부울 &, |와 함께 여러 값을 연결하는 데 사용됩니다. –