具有项目水平排列的 WPF ListView?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1041551/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF ListView with horizontal arrangement of items?
提问by Grokys
I want to lay out items in a ListView in a similar manner to the WinForms ListView in List mode. That is, where items are laid out not just vertically but horizontally in the ListView as well.
我想以类似于列表模式下的 WinForms ListView 的方式在 ListView 中布置项目。也就是说,项目在 ListView 中不仅垂直而且水平布置。
I don't mind if the items are laid out like this:
我不介意这些物品是否是这样布置的:
1 4 7
2 5 8
3 6 9
1 4 7
2 5 8
3 6 9
Or like this:
或者像这样:
1 2 3
4 5 6
7 8 9
1 2 3
4 5 6
7 8 9
As long as they are presented both vertically and horizontally in order to maximize the use of available space.
只要它们垂直和水平呈现,以最大限度地利用可用空间。
The closest I could find was this question:
我能找到的最接近的是这个问题:
How do I make WPF ListView items repeat horizontally, like a horizontal scrollbar?
如何使 WPF ListView 项目水平重复,就像水平滚动条一样?
Which only lays out the items only horizontally.
仅水平排列项目。
回答by rmoore
It sounds like what you are looking for is a WrapPannel, which will lay the items out horizontally until there is no more room, and then move to the next line, like this:
听起来您正在寻找的是WrapPanel,它将水平放置项目直到没有更多空间,然后移动到下一行,如下所示:
(MSDN)
alt text http://i.msdn.microsoft.com/Cc295081.b1c415fb-9a32-4a18-aa0b-308fca994ac9(en-us,Expression.10).png
( MSDN)
替代文本 http://i.msdn.microsoft.com/Cc295081.b1c415fb-9a32-4a18-aa0b-308fca994ac9(en-us,Expression.10).png
You also could use a UniformGrid, which will lay the items out in a set number of rows or columns.
您还可以使用UniformGrid,它将项目排列在一定数量的行或列中。
The way we get the items to arange using these other panels in a ListView, ListBox, or any form of ItemsControl is by changing the ItemsPanelproperty. By setting the ItemsPanel you can change it from the default StackPanel that is used by ItemsControls. With the WrapPanel we also should set the widths as shown here.
我们使用 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>
回答by Dennis
I recently research how to achieve this in WPF and found a good solution. What I wanted was to the replicate the List mode in Windows Explorer, i.e. top-to-bottom, then left-to-right.
我最近研究了如何在 WPF 中实现这一点并找到了一个很好的解决方案。我想要的是在 Windows 资源管理器中复制列表模式,即从上到下,然后从左到右。
Basically what you want to do override the ListBox.ItemsPanel
property to use a WrapPanel with it's orientation set to Vertical.
基本上你想要做的覆盖ListBox.ItemsPanel
属性以使用它的方向设置为垂直的 WrapPanel。
<ListBox>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
However this WILLbe slow when loading a large data set as it the wrap panel is not virtualised. This is important. So this task now becomes a little more as now you need to write your own VirtualizedWrapPanel by extending VirtualizedPanel and implementing IScrollInfo.
然而,这WILL加载大的数据集,因为它卷绕面板并不虚拟化时会很慢。这个很重要。所以这个任务现在变得有点多,因为现在你需要通过扩展 VirtualizedPanel 和实现 IScrollInfo 来编写你自己的 VirtualizedWrapPanel。
public class VirtualizedWrapPanel : VirtualizedPanel, IScrollInfo
{
// ...
}
This is as far as I got in my research before having to go off to another task. If you want more information or examples, please comment.
这是我在不得不开始另一项任务之前在我的研究中得到的。如果您需要更多信息或示例,请发表评论。
UPDATE. Ben Constable's has a great series on how to implement IScrollInfo.
更新。Ben Constable 有一个关于如何实现 IScrollInfo的精彩系列。
There are 4 articles in total. A really good read.
共有 4 篇文章。读得真好。
I have since implemented a virtualized wrap panel, it is not an easy task even with the help of the above series of articles.
我已经实现了一个虚拟化的环绕面板,即使有上述系列文章的帮助,这也不是一件容易的事。
回答by Arsen Zahray
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 analog to Windows Explorer's List option
这给了我一个很好的模拟 Windows 资源管理器的列表选项
回答by kns98
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>
回答by CularBytes
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.
除了@Dennis 的回答,关于 WrapPanel 失去虚拟化,我发现了一个很好的类,可以正确实现这一点。虽然 Ben Constable 建议的帖子(第 1 部分、第 2 部分、第 3 部分、第 4 部分)是一个很好的介绍,但我无法完全完成 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.
这是一个实现:https: //virtualwrappanel.codeplex.com/我已经用总共 3.300 个视频和照片对其进行了测试,加载列表本身当然有点长,但最终它正确地虚拟化了列表,没有滚动任何滞后。
- 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:
MVVM 风格的后端,所以这是在 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++;
}
}