WPF ListView avec disposition horizontale des éléments?

Je veux mettre en forme des éléments dans un ListView d’une manière similaire à WinForms ListView en mode liste. C’est-à-dire que les éléments sont également disposés non seulement verticalement mais horizontalement dans ListView.

Cela ne me dérange pas si les articles sont disposés comme ceci:

1 4 7
2 5 8
3 6 9

Ou comme ça:

1 2 3
4 5 6
7 8 9

Tant qu’ils sont présentés à la fois verticalement et horizontalement afin de maximiser l’utilisation de l’espace disponible.

Le plus proche que j’ai pu trouver était cette question:

Comment faire pour que les éléments de WPF ListView soient répétés horizontalement, comme une barre de défilement horizontale?

Qui ne dispose que les éléments horizontalement.

On dirait que ce que vous cherchez est un WrapPannel , qui étendra les éléments horizontalement jusqu’à ce qu’il n’y ait plus d’espace, puis passe à la ligne suivante, comme ceci:

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

Vous pouvez également utiliser un UniformGrid , qui déposera les éléments dans un nombre défini de lignes ou de colonnes.

La façon dont nous rassemblons les éléments à l’aide de ces autres panneaux dans ListView, ListBox ou dans n’importe quel autre élément ItemsControl consiste à modifier la propriété ItemsPanel . En définissant le ItemsPanel, vous pouvez le changer à partir du StackPanel par défaut utilisé par ItemsControls. Avec le WrapPanel, vous devez également définir les largeurs comme indiqué ici .

      ...  

J’ai récemment cherché comment y parvenir dans WPF et j’ai trouvé une bonne solution. Ce que je voulais, c’était reproduire le mode Liste dans l’Explorateur Windows, c’est-à-dire de haut en bas, puis de gauche à droite.

Fondamentalement, ce que vous voulez faire remplace la propriété ListBox.ItemsPanel pour utiliser un WrapPanel avec son orientation définie sur Vertical.

        

Cependant, ce sera lent lors du chargement d’un jeu de données volumineux, car le panneau de recouvrement n’est pas virtualisé. C’est important. Cette tâche devient donc un peu plus complexe, car vous devez maintenant écrire votre propre VirtualizedWrapPanel en étendant VirtualizedPanel et en implémentant IScrollInfo.

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

C’est dans la mesure où je suis entré dans mes recherches avant de devoir entreprendre une autre tâche. Si vous souhaitez plus d’informations ou d’exemples, veuillez commenter.

MISE À JOUR Ben Constable a une bonne série sur la façon d’implémenter IScrollInfo .

Il y a 4 articles au total. Une très bonne lecture.

J’ai depuis implémenté un panneau de recouvrement virtualisé, ce n’est pas une tâche facile, même avec l’aide de la série d’articles ci-dessus.

Dans mon cas, la meilleure option était d’utiliser:

       

Cela m’a donné un analogue décent à l’option de liste de Windows Explorer

de gauche à droite puis de haut en bas

       

En plus de la réponse de @ Dennis, à propos de la perte de virtualisation de WrapPanel, j’ai trouvé une classe intéressante qui l’implémente correctement. Bien que l’article proposé par Ben Constable ( partie 1 , partie 2 , partie 3 , partie 4 ) soit une bonne introduction, je ne pouvais pas terminer la tâche pour un panneau Wrap.

Voici une implémentation: https://virtualwrappanel.codeplex.com/ Je l’ai testé avec un total de 3.300 vidéos et photos, le chargement de la liste est bien sûr un peu long, mais finalement il virtualise correctement la liste, pas de défilement retard que ce soit.

  • Il y a quelques problèmes à ce code, voir l’onglet des problèmes sur la page ci-dessus.

Après avoir ajouté le code source à votre projet, par exemple le code source:

                     

Le back-end de style MVVM, donc à l’intérieur du ViewModel:

  public ObservableCollection 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 ssortingng title { get; set; } public ssortingng path { get; set; } public DateTime createDate { get; set; } public bool isSelected { get; set; } public Media() { mediaId = nextMediaId; nextMediaId++; } }