8
votes

Y a-t-il une façon d'utiliser la virtualisation avec des panneaux cachés ou des expansion?

J'essaie d'améliorer les performances avec mon application WPF et j'ai des problèmes avec un itemstrol complexe. Bien que j'ai ajouté la virtualisation, il y a toujours un problème de performance et je pense que j'ai travaillé pourquoi.

Chaque élément contient une série de zones extensibles. Donc, l'utilisateur voit un résumé au début mais peut expliquer en expansinant pour voir plus d'informations. Voici comment ça a l'air:

 Entrez la description de l'image ici

Comme vous pouvez le constater, il y a des itemstrols imbriqués. Donc, chacun des articles de niveau supérieur a une bouquet de commandes cachées. La virtualisation empêche les éléments hors écran de charger, mais pas les éléments cachés dans les objets eux-mêmes. En conséquence, la mise en page initiale relativement simple prend une période significative. Écraser autour de certaines de ces vues, 87% du temps sont passés à l'analyse et à la mise en page, et il faut quelques secondes à charger.

Je préférerais beaucoup que cela soit prise à 200 ms pour se développer lorsque (si!) L'utilisateur décide de, au lieu de 2 à charger la page dans son ensemble.

Demander des conseils vraiment. Je ne peux pas penser à une bonne façon d'ajouter les commandes à l'aide de MVVM. Existe-t-il une virtualisation basée sur l'expiteur ou la visibilité soutenue dans WPF ou créerais ma propre implémentation?

La figure 87% provient des diagnostics:

 Entrez la description de l'image ici


6 commentaires

Qu'est-ce que "Articles cachés dans les articles eux-mêmes" ? La virtualisation ne créera pas contentpresenter , mais quelque part que vous avez observablecollection <> Ce qui doit être entièrement chargé. Alors, qu'est-ce que ce 2S comprend? Avez-vous fait du profilage pour voir ce qui est réellement un goulot d'étranglement?


Voulez-vous virtualiser une partie de l'article qui est à l'intérieur Expander (pour les éléments créés)? Si oui, vous pouvez gérer l'état effondré dans ViewModel à Ajouter plus de données lors de son élargissement (par exemple, l'utilisation d'un objet pour contenir ce modèle de données et de données pour créer un élément visuel quand il est pas null ).


C'est comme ça que c'est la mise en page. Vous pouvez retarder l'obtention des données jusqu'à ce qu'il soit ouvert. Je suis surpris que cela prend 2 secondes.


@ContentPresenter, Articles cachés = Visibilité.Collapté, réglé sur Visible lorsqu'il est affiché. C'est une très bonne idée, je peux simplement définir les collections observables lorsque l'état de visibilité a été modifié, ce serait super facile. Je vais voir comment ça gère.


HMM, j'ai complètement enlevé les expanses et je suis confronté à des moments de charge similaires. J'ai ajouté une édition


@Sinatrice bonne idée, fera.


4 Réponses :


7
votes

Si vous avez simplement

public ObservableCollection<Item> Items = ... // bind ItemsControl.ItemsSource to this

class Item : INotifyPropertyChanged
{
    bool _isExpanded;
    public bool IsExpanded // bind Expander.IsExpanded to this
    {
        get { return _isExpanded; }
        set
        {
            Data = value ? new SubItem(this) : null;
            OnPropertyChanged(nameof(Data));
        }
    }

    public object Data {get; private set;} // bind item Content to this
}

public SubItem: INotifyPropertyChanged { ... }


1 commentaires

L'utilisation de modèles est une bonne idée, je l'ai mis en œuvre à peu près à la manière dont vous décrivez et la performance est très améliorée. Merci!



2
votes

Je pensais mettre les détails de la solution, qui est à peu près une mise en œuvre directe de la réponse de Sinatr.

J'ai utilisé un contrôle de contenu, avec un sélecteur de modèle de données très simple. Le sélecteur de modèle vérifie simplement si l'élément de contenu est NULL et choisit entre deux modèles de données: P>

    private bool expanded;
    public bool Expanded
    {
        get { return expanded; }
        set
        {
            if (expanded != value)
            {
                expanded = value;
                NotifyOfPropertyChange(() => VirtualizedViewModel);
                NotifyOfPropertyChange(() => Expanded);
            }
        }
    }


    public MyViewModel VirtualizedViewModel
    {
        get
        {
            if (Expanded)
            {
                return this;
            }
            else
            {
                return null;
            }
        }
    }


0 commentaires

0
votes

Un moyen plus facile d'y parvenir est de modifier la visibilité par défaut du contenu à effondrer. Dans ce cas, WPF ne le créera pas initialement, mais uniquement lorsqu'un déclencheur le réglait visible: xxx

ici "Développement" est le contenuPRESENTATEUR dans le contrôle par défaut du contrôle de l'extension. Notez que cela a été corrigé dans .NET - voir le style par défaut des sources WPF sur Github .

Si vous avez une version plus ancienne, vous pouvez toujours utiliser ce modèle de contrôle fixe pour mettre à jour l'ancien un style implicite.

Vous pouvez appliquer la même technique à tout autre panneau ou contrôle.

Il est facile de vérifier si le contrôle a déjà été créé avec Snoop . Une fois que vous l'avez attachée à votre application, vous pouvez filtrer l'arborescence visuelle avec la zone de texte en haut à gauche. Si vous ne trouvez pas un contrôle dans l'arbre, cela signifie qu'il n'a pas encore été créé.


2 commentaires

J'ai essayé de suivre cela et je ne peux pas le faire fonctionner, je pense qu'un exemple plus complet aiderait. "TargetName" n'est pas autorisé sur les déclencheurs de style, les membres de la collection de déclencheurs doivent être des extrigreux événementiels qui n'ont pas de "propriété". Deux des erreurs que j'ai eues.


Jetez un coup d'œil aux sources liées de GitHub. Vous pouvez voir que le nom TargetName = "Développement" est utilisé à l'intérieur de ControlTemplate.Triggers. Le moyen le plus simple d'atteindre le chargement paresseux est de mettre à jour une nouvelle version de Framework. Si ce n'est pas une option, vous pouvez utiliser un outil tel que le style WPF Snooper pour obtenir le style Expander par défaut à partir de votre version .NET, étendez-la avec ce déclencheur et remplacez le style par défaut avec votre style modifié dans votre application.



1
votes

Cette solution simple m'a aidé: xxx


1 commentaires

Cette solution est très simple et rapide, il semble que la visibilité du contenu de l'expandeur est liée à celle-ci d'augmenter la propriété affectera énormément le rendu. Le seul problème est que l'effondrement des articles n'est plus animé mais instantané