Nice programing

항목의 수평 배열이있는 WPF ListView?

nicepro 2021. 1. 5. 21:12
반응형

항목의 수평 배열이있는 WPF ListView?


목록 모드의 WinForms ListView와 유사한 방식으로 ListView에 항목을 배치하고 싶습니다. 즉, ListView에서 항목이 세로로만 배치되는 것이 아니라 가로로도 배치됩니다.

항목이 다음과 같이 배치 되어도 상관 없습니다.

1 4 7
2 5 8
3 6 9

또는 다음과 같이 :

1 2 3
4 5 6
7 8 9

사용 가능한 공간을 최대한 활용하기 위해 세로 및 가로로 모두 표시되는 경우.

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

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

항목을 수평으로 만 배치합니다.


찾고있는 것이 WrapPannel것처럼 들리는데 , 더 이상 공간이 없을 때까지 항목을 수평으로 배치 한 다음 다음과 같이 다음 줄로 이동합니다.

( MSDN )
대체 텍스트 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.ItemsPanel것은 Vertical로 설정된 방향으로 WrapPanel을 사용 하도록 속성을 재정의합니다 .

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

그러나이 랩 패널이 가상화되지 않은 그것으로 큰 데이터 세트를로드 할 때 속도가 느릴 수. 이것은 중요하다. 이제 VirtualizedPanel을 확장하고 IScrollInfo를 구현하여 자신 만의 VirtualizedWrapPanel을 작성해야하므로이 작업은 이제 조금 더 많아졌습니다.

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

이것은 다른 작업으로 넘어 가기 전에 내가 연구 한 한까지입니다. 더 많은 정보 나 예를 원하시면 의견을 남겨주세요.

업데이트 . Ben Constable의 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 탐색기의 목록 옵션에 알맞은 아날로그를주었습니다.


for left to right then top to bottom use

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

In addition to @Dennis's answer, about the WrapPanel losing Virtualization, I have found a nice class that correctly implements this. While the suggested post by Ben Constable (Part 1, Part 2, Part 3, Part 4) is a nice introduction, I couldn't quite complete the task for a Wrap Panel.

Here is an implementation: https://virtualwrappanel.codeplex.com/ I've tested it with total of 3.300 video's and photo's, loading the list itself is of course a bit long, but eventually it is correctly virtualizing the list, no scroll lag whatsoever.

  • There are some issues to this code, see the issues tab on the page above.

After adding the source code to your project, example source code:

   <!--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 style back-end, so this is inside the ViewModel:

    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++;
    }
}

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

반응형