source

WPF List View를 사용하여 항목을 수평으로 배열하시겠습니까?

factcode 2023. 4. 14. 22:10
반응형

WPF List View를 사용하여 항목을 수평으로 배열하시겠습니까?

목록 모드의 WinForms ListView와 같은 방법으로 ListView에 항목을 배치하고 싶습니다.즉, ListView에서 항목이 세로뿐만 아니라 가로로 배치됩니다.

아이템은 다음과 같이 배치되어 있어도 상관없습니다.

1 4 7
5 825 8

또는 다음과 같이 합니다.

1 2 3
4 5 6
899

사용 가능한 공간을 최대한 활용하기 위해 세로 및 가로로 모두 표시되어야 합니다.

내가 찾을 수 있는 가장 가까운 질문은 다음과 같다:

WPF List View 항목을 가로 스크롤 막대처럼 가로로 반복하려면 어떻게 해야 합니까?

그것은 오직 수평으로만 물건을 배치한다.

찾고 있는 것은 WrapPannel인 것 같습니다.WrapPannel은 빈자리가 없어질 때까지 아이템을 수평으로 배치한 후 다음 행으로 이동합니다.

(MSDN)
text http://i.msdn.microsoft.com/Cc295081.(en-us,Expression.10).pngalt 텍트http://i.msdn.microsoft.com/Cc295081.b1c415fb-9a32-4a18-aa0b-308fca994ac9(en-us,Expression.10).png http://i.msdn.microsoft.com/Cc295081.b1c415fb-9a32-4a18-aa0b-308fca994ac9(en-us,Expression.10).png

또한 UniformGrid를 사용하면 항목이 설정된 수의 행 또는 열에 배치됩니다.

ListView, ListBox 또는 모든 형태의 ItemsControl에서 이러한 다른 패널을 사용하여 항목을 정렬하려면 ItemsPanel 속성을 변경합니다.ItemsPanel을 설정하면 ItemsControls에서 사용되는 기본 StackPanel에서 변경할 수 있습니다.WrapPanel에서는 다음과 같이 폭도 설정해야 합니다.

<ListView>
   <ListView.ItemsPanel>
      <ItemsPanelTemplate>
         <WrapPanel Width="{Binding (FrameworkElement.ActualWidth), 
            RelativeSource={RelativeSource AncestorType=ScrollContentPresenter}}"
            ItemWidth="{Binding (ListView.View).ItemWidth, 
            RelativeSource={RelativeSource AncestorType=ListView}}"
            MinWidth="{Binding ItemWidth, RelativeSource={RelativeSource Self}}"
            ItemHeight="{Binding (ListView.View).ItemHeight, 
            RelativeSource={RelativeSource AncestorType=ListView}}" />
      </ItemsPanelTemplate>
   </ListView.ItemsPanel>
...
</ListView>

저는 최근 WPF에서 이를 달성하는 방법을 연구하여 좋은 해결책을 찾았습니다.Windows 탐색기의 목록 모드를 위에서 아래로, 왼쪽에서 오른쪽으로 복제하고 싶었습니다.

은 하고 싶은 일을 .ListBox.ItemsPanelWrapPanel Vertical wrap로로 。

<ListBox>
  <ListBox.ItemsPanel>
    <ItemsPanelTemplate>      
      <WrapPanel Orientation="Vertical"/>
    </ItemsPanelTemplate>
  </ListBox.ItemsPanel>
</ListBox>

그러나 랩 패널이 가상화되어 있지 않기 때문에 대용량 데이터 세트를 로드할 때는 속도가 느려집니다.이게 중요해요.이 작업은 Virtualized Panel을 확장하고 IScrollInfo를 구현하여 자체 Virtualized WrapPanel을 작성해야 하기 때문에 조금 더 쉬워졌습니다.

public class VirtualizedWrapPanel : VirtualizedPanel, IScrollInfo
{
   // ...
}

다른 일을 하러 가기 전에 여기까지 연구했습니다.자세한 정보나 예를 원하시면 코멘트를 부탁드립니다.

업데이트. Ben Constable's는 IScrollInfo 구현 방법에 대한 훌륭한 시리즈를 보유하고 있습니다.

총 4개의 기사가 있습니다.정말 좋은 읽을거리야.

그 후 가상화 랩 패널을 실장했습니다만, 상기의 일련의 기사의 도움을 받아도, 이것은 간단한 작업이 아닙니다.

제 경우, 가장 좋은 방법은 다음을 사용하는 것입니다.

        <ListView.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel Orientation="Vertical"
                    MaxHeight="{Binding (FrameworkElement.ActualHeight), RelativeSource={RelativeSource AncestorType=ScrollContentPresenter}}"
                               ItemWidth="{Binding (ListView.View).ItemWidth, RelativeSource={RelativeSource AncestorType=ListView}}"
                               MinHeight="{Binding ItemHeight, RelativeSource={RelativeSource Self}}"
                               ItemHeight="{Binding (ListView.View).ItemHeight, RelativeSource={RelativeSource AncestorType=ListView}}"/>
            </ItemsPanelTemplate>
        </ListView.ItemsPanel>

Windows 탐색기 목록 옵션과 비슷한 기능을 사용할 수 있게 되었습니다.

왼쪽에서 오른쪽으로, 위에서 아래로 사용

      <ListView.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel Orientation="Horizontal" 
                     MaxWidth="{Binding ActualWidth, Mode=OneWay, 
                       RelativeSource={RelativeSource FindAncestor, 
                       AncestorType={x:Type er:MainWindow}}}"/>
            </ItemsPanelTemplate>
        </ListView.ItemsPanel>

WrapPanel이 가상화를 잃었다는 @Dennis의 답변과 더불어 이를 올바르게 구현하기 위한 훌륭한 클래스를 찾았습니다.Ben Constable의 추천 투고(Part 1, Part 2, Part 3, Part 4)는 좋은 소개이지만, 저는 Wrap Panel의 작업을 완료하지 못했습니다.

구현: https://virtualwrappanel.codeplex.com/ 총 3.300개의 비디오와 사진을 사용하여 테스트했습니다.목록 로딩 자체는 물론 조금 길지만 결국 스크롤 지연 없이 목록을 올바르게 가상화하고 있습니다.

  • 이 코드에는 몇 가지 문제가 있습니다.위 페이지의 문제 탭을 참조하십시오.

프로젝트에 소스 코드를 추가한 후 소스 코드 예:

   <!--in your <Window> or <UserControl> tag -->
  <UserControl
        xmlns:hw="clr-namespace:Project.Namespace.ToClassFile" >
   <!--...-->

    <ListView x:Name="lvImages" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="3" Margin="10" Height="auto" 
             ItemsSource="{Binding ListImages}"
              ScrollViewer.HorizontalScrollBarVisibility="Disabled" >
        <ListView.ItemsPanel>
            <ItemsPanelTemplate>
                <hw:VirtualizingWrapPanel Orientation="Horizontal" />
            </ItemsPanelTemplate>
        </ListView.ItemsPanel>
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Vertical" Margin="5" MaxHeight="150">
                    <TextBlock Text="{Binding title}" FontWeight="Bold"/>
                    <Image Source="{Binding path, IsAsync=True}" Height="100"/>
                    <TextBlock Text="{Binding createDate, StringFormat=dd-MM-yyyy}"/>

                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

MVVM 스타일의 백엔드는 View Model 내부에 있습니다.

    public ObservableCollection<Media> ListImages
    {
        get
        {
            return listImages;
        }
        set { listImages = value; OnPropertyChanged(); }
    }


     //Just load the images however you do it, then assign it to above list.
//Below is the class defined that I have used.
public class Media
{
    private static int nextMediaId = 1;
    public int mediaId { get; }
    public string title { get; set; }
    public string path { get; set; }
    public DateTime createDate { get; set; }
    public bool isSelected { get; set; }

    public Media()
    {
        mediaId = nextMediaId;
        nextMediaId++;
    }
}

언급URL : https://stackoverflow.com/questions/1041551/wpf-listview-with-horizontal-arrangement-of-items

반응형