WPF ListView with horizontal layout?

I want to lay out items in a ListView in the same way as WinForms ListView in list mode. That is, where the elements are located not only vertically, but also horizontally in the ListView.

I do not mind if the elements are laid out as follows:

1 4 7
2 5 8
3 6 9

Or like this:

1 2 3
4 5 6
7 8 9

While they are presented both vertically and horizontally, to maximize the use of available space.

The closest I could find is the question:

How to make WPF ListView items repeat horizontally, like a horizontal scrollbar?

Which only sets out the elements only horizontally.

+54
listview layout wpf
Jun 24 '09 at 23:55
source share
5 answers

It looks like you are looking for a WrapPannel that will place elements horizontally until there is more space, and then go to the next line, for example:

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

You can also use UniformGrid , which will output the elements in a given number of rows or columns.

The way we get items for argeziya using these other panels in ListView, ListBox or any form of ItemsControl is changing ItemsPanel . By setting the ItemsPanel, you can change it from the default StackPanel used by ItemsControls. With the WrapPanel, we also need to set the width as shown here .

<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> 
+99
Jun 25 '09 at 1:38
source share

I recently researched how to achieve this in WPF, and found a good solution. I wanted list mode replication in Windows Explorer, that is, from top to bottom, and then from left to right.

Basically, you want to override the ListBox.ItemsPanel property to use the WrapPanel with the orientation set to Vertical.

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

However, this WILL will be slow when loading a large dataset, since the transfer panel is not virtualized. It is important. So now this task is getting a little bigger, because now you need to write your own VirtualizedWrapPanel, expanding VirtualizedPanel and implementing IScrollInfo.

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

This is until I got into my research before moving on to another task. If you need more information or examples, please comment.

UPDATE Ben Constable has an excellent series on how to implement IScrollInfo .

Only 4 articles. Very good read.

Since then I have implemented a virtualized wrapper panel, this is not an easy task even with the help of the above series of articles.

+21
Jun 25 '09 at 6:59
source share

In my case, the best option was to use:

  <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> 

This gave me a decent counterpart to the Windows Explorer list option.

+8
May 4 '12 at
source share

from left to right, and from top to bottom -

  <ListView.ItemsPanel> <ItemsPanelTemplate> <WrapPanel Orientation="Horizontal" MaxWidth="{Binding ActualWidth, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type er:MainWindow}}}"/> </ItemsPanelTemplate> </ListView.ItemsPanel> 
+2
Jun 23 '14 at 17:37
source share

In addition to @ Dennis's answer about WrapPanel losing virtualization, I found a nice class that implements this correctly. While Ben Constable's proposed position ( Part 1 , Part 2 , Part 3 , Part 4 ) is a pleasant introduction, I could not fully complete the task for the Wrap Panel.

Here is the implementation: https://virtualwrappanel.codeplex.com/ I tested it with a total of 3,300 videos and photos, loading the list itself is, of course, a bit long, but it ultimately virtualizes the list without scrolling.

  • There are some problems in this code, see the Problems tab on the page above.

After adding the source code to your project, an example of the 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> 

The style is MVVM-style, so it 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++; } } 
+1
May 09 '16 at 19:48
source share



All Articles