WPF C # Comment puis-je filtrer un ObservableCollection ou QueryableCollectionView?

Je veux filtrer et lister toutes les catégories qui ont le même code de catégorie dupliqué.

Comme code: Test123 comprend ces catégories. En d'autres termes, le code de catégorie doit être unique.

J'ai essayé cela avec QueryableCollectionView:

var test = CategoryCollection.GroupBy(Category => Category.Code).Where(w => w.Count() > 1);

Mais ça n'a pas marché.

Mon exemple de code:

    public ObservableCollection<Category> GetCategory
    {
        get
        {
            this._getCategory = GetCategory();
            this._getCategory.GroupBy(category => category.Code).ToList().Where(w => w.Count() > 1); ;
            this._getCategory = new ObservableCollection<Category>(_getCategory);
            return this._getCategory.               
        }
        set
        {
            if (this._getCategory != value)
            {
                this._getCategory = value;
                this.OnPropertyChanged("GetCategory");
            }
        }
    }
0
user6870932 20 nov. 2018 à 16:53

3 réponses

Meilleure réponse

J'ai créé un exemple de code qui fonctionne comme vous l'avez décrit maintenant, voir ci-dessous:

MainWindow.xaml

<Window x:Class="TestWpfApplication.MainWindowView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Title="MainWindow" 
    Height="450" 
    Width="800">

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>

    <ListBox Grid.Row="0" Grid.Column="0" Name="CategoryListBox" ItemsSource="{Binding Path=CategoryCollection}" DisplayMemberPath="Description" />
    <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding ElementName=CategoryListBox, Path=SelectedItem.Code}" />
</Grid>

MainWindow.xaml.cs

using System.Windows;

namespace TestWpfApplication
{
    public partial class MainWindowView : Window
    {
        private readonly MainWindowViewModel _mainWindowViewModel = new MainWindowViewModel();

        public MainWindowView()
        {
            InitializeComponent();

            DataContext = _mainWindowViewModel;
        }
    }
}

MainWindowViewModel.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Data;

namespace TestWpfApplication
{
    internal class MainWindowViewModel
    {
        private readonly List<Category> _categories;

        public MainWindowViewModel()
        {
            _categories = new List<Category>
            {
                new Category {Code = 1, Description = "Blah"},
                new Category {Code = 1, Description = "Blah"},
                new Category {Code = 2, Description = "Pop"},
                new Category {Code = 3, Description = "No"},
                new Category {Code = 3, Description = "No"},
                new Category {Code = 4, Description = "Yes"}
            };

            HookUpCategoryEvents();

            CategoryCollection = CollectionViewSource.GetDefaultView(_categories);
            CategoryCollection.Filter = OnlyShowIfMoreThanOne;
        }

        private bool OnlyShowIfMoreThanOne(object obj)
        {
             Category item = obj as Category;

             return _categories.Count(c => c.Code == item.Code) > 1;
        }

        public ICollectionView CategoryCollection { get; }

        private void HookUpCategoryEvents()
        {
            // If you add items or remove them at any point then you need to call this method
            // It removes the event so you don't get existing items being 'hooked up' double or more times

            foreach (var category in _categories)
            {
                category.CodeChanged -= CategoryOnCodeChanged;
                category.CodeChanged += CategoryOnCodeChanged;
            }
         }

        private void CategoryOnCodeChanged(object sender, EventArgs e)
        {
            CategoryCollection.Refresh();
        }
    }
}

Category.cs

using System;

namespace TestWpfApplication
{
    public class Category
    {
        private int _code;
        private string _description;

        public event EventHandler CodeChanged;

        public int Code
        {
            get => _code;
            set
            {
                if (_code != value)
                {
                    _code = value;
                    OnCodeChanged();
                }
            }
        }

        public string Description
        {
            get => _description;
            set => _description = value;
        }

        private void OnCodeChanged()
        {
            CodeChanged?.Invoke(this, EventArgs.Empty);
        }
    }
}

Cela affiche un ListBox simple qui est défini pour afficher la propriété Description de la classe Category et un TextBox qui affiche le SelectedItem.Code de ListBox. Dans le ViewModel, ICollectionView a un filtre qui lui est appliqué afin qu'il n'affiche que les éléments dont ces codes apparaissent plus d'une fois. Un événement est déclenché à partir de la classe Category lors de la définition de la propriété Code (à partir du TextBox) que MainWindowViewModel écoute et utilise pour appeler .Refresh () sur ICollectionView. Il n'y a aucune validation ou autre chose que vous voudriez dans le code de production, mais cela devrait vous montrer les bases de ce que vous voulez.

0
Coops 21 nov. 2018 à 09:04
List<Category> listResult= yourObservableCollection.GroupBy(c => c.Code)
.Select(cl=>new Caegory
{
    Code=cl.First().Code;
    // other parameters of Category here
}).ToList().Where(w=>w.Count()>1);
ObservableCollection<Category> result=new ObservableCollection<Category>(listResult);

Je ne sais pas sur QueryableCollectionView, mais pour ObservableCollection cela fonctionne

0
Siegfried.V 21 nov. 2018 à 06:31

Var test = CategoryCollection.GroupBy (Category => Category.Code) .toList (). Where (w => w.Count ()> 1);

0
Umar Draz 20 nov. 2018 à 14:17