簡體   English   中英

WPF ListView與項目的水平排列?

[英]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

只要它們在垂直和水平方向呈現,以便最大限度地利用可用空間。

我能找到的最接近的是這個問題:

如何使WPF ListView項目水平重復,如水平滾動條?

只能水平放置項目。

聽起來你正在尋找的是一個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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM