![](/img/trans.png)
[英]WPF ListView does not display horizontal scroll bars if there are no items in the list
[英]WPF ListView with horizontal arrangement of items?
我想以類似於列表模式下的WinForms ListView的方式在ListView中布置項目。 也就是說,ListView中的項目不僅在垂直方向而且在水平方向上布局。
我不介意這些物品的布局是這樣的:
1 4 7
2 5 8
3 6 9
或者像這樣:
1 2 3
4 5 6
7 8 9
只要它們在垂直和水平方向呈現,以便最大限度地利用可用空間。
我能找到的最接近的是這個問題:
只能水平放置項目。
聽起來你正在尋找的是一個WrapPannel ,它會將項目水平放置,直到沒有空間,然后移動到下一行,如下所示:
( MSDN )
alt text 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
屬性以使用WrapPanel,其方向設置為Vertical。
<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資源管理器列表選項的模擬
從左到右,然后從上到下使用
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"
MaxWidth="{Binding ActualWidth, Mode=OneWay,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type er:MainWindow}}}"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
除了@Dennis的回答,關於WrapPanel失去Virtualization,我找到了一個很好的類來正確實現它。 雖然Ben Constable的建議帖子( 第1部分 , 第2部分 , 第3部分 , 第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樣式的后端,所以這是在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++;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.