Question

Je suis en utilisant WPF, et de tenter de suivre le modèle MVVM.Notre équipe a décidé d'utiliser le Xceed contrôle DataGrid, et je vais avoir quelques difficultés à la faire tenir dans le pattern MVVM.

Une exigence que je dois répondre, c'est que j'ai besoin de savoir quand un utilisateur modifie un filtre de colonne dans la grille.Je suis conscient que la dernière version du contrôle DataGrid est un événement qui est déclenché pour cela, mais malheureusement, je dois utiliser une version plus ancienne du contrôle.

Après avoir cherché pendant un certain temps, j'ai trouvé cette post.Il dit que j'ai besoin d'un hameçon INotifyCollectionChanged gestionnaire pour chacun de la liste possible des filtres.Cela fonctionne, mais il dit aussi que j'ai besoin de décrocher les gestionnaires à chaque fois que la source de ligne de la grille.

J'ai été en mesure de le faire fonctionner quand j'définir explicitement la source de ligne dans le code-behind de la page (et dans ma première tentative dans le ModelView à l'aide d'une référence directe à la vue gasp!)

Le premier problème que je rencontre est de savoir comment faire cela sans avoir la logique dans le code derrière ou dans le ViewModel.Ma solution a été d'étendre la DataGridControl de classe et d'ajouter le code suivant:

    private IDictionary<string, IList> _GridFilters = null;
    public MyDataGridControl() : base()
    {
        TypeDescriptor.GetProperties(typeof(MyDataGridControl))["ItemsSource"].AddValueChanged(this, new EventHandler(ItemsSourceChanged));
    }

    void ItemsSourceChanged(object sender, EventArgs e)
    {
        UnsetGridFilterChangedEvent();
        SetGridFilterChangedEvent();
    }

    public void SetGridFilterChangedEvent()
    {
        if (this.ItemsSource == null)
            return;

        DataGridCollectionView dataGridCollectionView = (DataGridCollectionView)this.ItemsSource;

        _GridFilters = dataGridCollectionView.AutoFilterValues;

        foreach (IList autofilterValues in _GridFilters.Values)
        {
            ((INotifyCollectionChanged)autofilterValues).CollectionChanged += FilterChanged;
        }
    }

    /*TODO: Possible memory leak*/
    public void UnsetGridFilterChangedEvent()
    {
        if (_GridFilters == null)
            return;

        foreach (IList autofilterValues in _GridFilters.Values)
        {
            INotifyCollectionChanged notifyCollectionChanged = autofilterValues as INotifyCollectionChanged;

            notifyCollectionChanged.CollectionChanged -= FilterChanged;
        }

        _GridFilters = null;
    }

Cela me conduire à mon prochain problème;Je suis assez sûr que le temps que les ItemsSourceChanged méthode est appelée, la collection de AutoFilterValues a déjà changé, donc je ne peut pas efficacement décrocher les gestionnaires.

Suis-je en droit de supposer cela?Et peut-on penser à une meilleure façon de gérer ces gestionnaires tout en permettant toujours à moi de garder cette fonctionnalité encapsulée dans ma classe étendue?

Désolé pour la longueur du post, et merci d'avance pour l'aide!

-Funger

Était-ce utile?

La solution

Il est exact que les AutoFilterValues aura déjà changé à ce point, vous serez en décrochant le mauvais gestionnaires, entraînant une fuite de mémoire.

La solution est très facile.Faire exactement ce que vous faites, mais l'utilisation d'un List<IList> au lieu de simplement le référencement AutoFilterValues:

private List<IList> _GridFilters;

et l'utilisation ToList() pour faire une copie de l'filtres vous définir des gestionnaires d'événements sur:

_GridFilters = dataGridCollectionView.AutoFilterValues.Values.ToList();

Depuis _GridFilters est maintenant un List<IList>, vous aurez également à modifier les boucles:

foreach(IList autofilterValues in _GridFilters) 
  ...

La raison pour laquelle cela fonctionne est que la liste d'anciennes listes de filtres est copié dans _GridFilters, plutôt que de simplement le référencement du AutoFilterValues de la propriété.

C'est une belle technique générale est applicable dans de nombreuses situations.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top