Увеличить скорость фильтрации DataGrid

Как увеличить скорость фильтрации ?

Логика фильтрации:

  • Пользователь выбирает Course в CoursesView;
  • Приложение фильтрует CoursesStudentsJoinView в зависимости от Course;
  • Приложение фильтрует StudentsView в зависимости от CoursesStudentsJoinView (исключает из StudentsView студентов Student, которые имеются в CoursesStudentsJoinView);

Это всё работает медленно.
На каждом шаге длительность работы приложения 1,5-3,0с.
Как правильно организовать решение или что сделать чтобы существующее решение работало быстрее?
Как это сделать в минимальном исполнении: NET Framework, без DI, IoC, интерфейсов для частей проекта.

CoursesStudentsJoinView работает с коллекцией элементов CourseStudentJoin.
CourseStudentJoin является аналогом View в БД.
CourseStudentJoin связывает в одну таблицу CourseStudent и Student поле NameStudent

Планируемая логика приложения:
- Пользователь добавляет курсы Course в CoursesView;
- Пользователь выбирает Course в CoursesView;
- Пользователь добавляет в CoursesStudentsJoinView студента Student из StudentsView;
- т.е.
- Пользователь в StudentsView выбирает студента Student;
- Пользователь в StudentsView нажимает кнопку AddInCoursesStudentsJoinView;
- Приложение удаляет студента Student из StudentsView и добавляет студента в CoursesStudentsJoinView.

Student с id от 11 до 21 исключены из StudentsView потому, что уже хранятся в CoursesStudentsJoinView.

Модель:

  • Course.cs
  • Student.cs
  • CourseStudent.cs
  • CourseStudentJoin.cs

Проект: https://github.com/jhon65496/FacultyWpfApp1ButtonStudents


Картинка-1
введите сюда описание изображения

Картинка-2
введите сюда описание изображения

Model

Course

public class Course
{
    public int IdCourse { get; set; }
    public int Sort { get; set; }
    public string NameCourse { get; set; }
    public string AliasCourse { get; set; }    
    public string Description { get; set; }    
}

Student

public class Student
{
    public int IdStudent { get; set; }
    public int Sort { get; set; }
    public string NameStudent { get; set; }
    public string AliasStudent { get; set; }    
    public string Description { get; set; }
    
}

CourseStudent

public class CourseStudent
{
    // CourseStudent
    public int IdCourseStudent { get; set; }
    public int IdStudent { get; set; }
    public int IdCourse { get; set; }
    public int Sort { get; set; }
}

CourseStudentJoin

Это аналог View(CourseStudent + Student) в БД.

public class CourseStudentJoin  
{   
    public int IdCourseStudent { get; set; }
    public int IdCourse { get; set; }
    public int IdStudent { get; set; }
    public string NameStudent { get; set; }
}

Логика фильтрации

Пользователь в CoursesViewModel выбирает курс.
CoursesViewModel передаёт выбранный курс SelectedCourse в MainWindowViewModel в свойство SelectedCourse.
Код: this.mainWindowViewModel.SelectedCourse = SelectedCourse;

CoursesViewModel

public Course SelectedCourse
{
    get { return _selectedCourse; }
    set
    {
        _selectedCourse = value;
        
        this.mainWindowViewModel.SelectedCourse = SelectedCourse;
        
        RaisePropertyChanged(nameof(SelectedCourse));
    }
}

MainWindowViewModel передаёт выбранный курс selectedCourse в CoursesStudentsJoinViewModel.CourseFilter.
Код: coursesStudentsJoinViewModel.CourseFilter = selectedCourse;

MainWindowViewModel

 public Course SelectedCourse
{
    get { return selectedCourse; }
    set
    {
        selectedCourse = value;

        // Установить критерий фильтрации для `CoursesStudentsJoinViewModel`
        coursesStudentsJoinViewModel.CourseFilter = selectedCourse;

        // Установить критерий фильтрации для `StudentsViewModel`
        var cSJ = coursesStudentsJoinViewModel.GetCoursesStudentsJoin(selectedCourse);
        this.studentsViewModel.LoadDataUnion(cSJ);

        RaisePropertyChanged(nameof(SelectedCourse));
    }
}

Фильтруем CoursesStudentsJoinViewModel
CoursesStudentsJoinViewModel

#region Filter == === === === === ==
private Course _сourseFilter;

public Course CourseFilter
{
    get { return _сourseFilter; }
    set
    {
        _сourseFilter = value;
        _CoursesStudentsJoinsViewSource.View.Refresh();
    }
}


private void OnCoursesStudentsJoinsFilter(object sender, FilterEventArgs e)
{
    //.... Code
    if (courseStudentJoin.IdCourse == CourseFilter.IdCourse)
    {
        e.Accepted = true;
    }
    else
    {
        e.Accepted = false;
    }
}

#region CollectionView
private CollectionViewSource _CoursesStudentsJoinsViewSource;

public ICollectionView CoursesStudentsJoinsView => _CoursesStudentsJoinsViewSource?.View;
#endregion

#endregion

Возвращаемся в MainWindowViewModel.
В MainWindowViewModel выполняем:
- в CoursesStudentsJoinViewModel фильтруем ObservableCollection<CourseStudentJoin> CoursesStudentsJoins;
- из CoursesStudentsJoinViewModel получаем отфильтрованную коллекцию ObservableCollection<CourseStudentJoin> CoursesStudentsJoins;
В CoursesStudentsJoinViewModel свойство ObservableCollection<CourseStudentJoin> CoursesStudentsJoins заполняется при создании CoursesStudentsJoinViewModel .

В MainWindowViewModel Код:

var cSJ = coursesStudentsJoinViewModel.GetCoursesStudentsJoin(selectedCourse);
this.studentsViewModel.LoadDataUnion(cSJ);

CoursesStudentsJoinViewModel

// CoursesStudentsJoins
private ObservableCollection<CourseStudentJoin> _coursesStudentsJoin;

public ObservableCollection<CourseStudentJoin> CoursesStudentsJoins
{
    get { return _coursesStudentsJoin; }
    set
    {
        _coursesStudentsJoin = value;

        _CoursesStudentsJoinsViewSource = new CollectionViewSource();
        _CoursesStudentsJoinsViewSource.Source = value;
        _CoursesStudentsJoinsViewSource.Filter += OnCoursesStudentsJoinsFilter;
        _CoursesStudentsJoinsViewSource.View.Refresh(); // 

        // RaisePropertyChanged(nameof(CoursesStudentsJoins));
        // CoursesStudentsJoinsView
        RaisePropertyChanged(nameof(CoursesStudentsJoinsView));
    }
}

public ObservableCollection<CourseStudentJoin> GetCoursesStudentsJoin(Course course)
{
    int IdCourse = course.IdCourse;

    var res = CoursesStudentsJoins.Where(cSJ => cSJ.IdCourse == IdCourse).ToList();
    var coursesStudentsJoins = new ObservableCollection<CourseStudentJoin>(res);

    return coursesStudentsJoins;
}

MainWindowViewModel

 public Course SelectedCourse
{
    get { return selectedCourse; }
    set
    {
        selectedCourse = value;

        // Установить критерий фильтрации для `CoursesStudentsJoinViewModel`
        coursesStudentsJoinViewModel.CourseFilter = selectedCourse;

        // Установить критерий фильтрации для `StudentsViewModel`
        var cSJ = coursesStudentsJoinViewModel.GetCoursesStudentsJoin(selectedCourse);
        this.studentsViewModel.LoadDataUnion(cSJ);

        RaisePropertyChanged(nameof(SelectedCourse));
    }
}

Передаём отфильтрованный ObservableCollection<CourseStudentJoin> CoursesStudentsJoins в StudentsViewModel
Код MainWindowViewModel:
this.studentsViewModel.LoadDataUnion(cSJ);

В StudentsViewModel
- метод LoadDataUnion(ObservableCollection<CourseStudentJoin> courseStudentJoin) исключает из ObservableCollection<Student> Students студунтов. которые содержаться в ObservableCollection<CourseStudentJoin> courseStudentJoin
- результат помещает в ObservableCollection<Student> StudentsView
- ObservableCollection<Student> StudentsView отображаем в представлении StudentsView.xaml

ObservableCollection<Student> Students - хранит в себе всех студентов. Заполняется при создании StudentsViewModel .

MainWindowViewModel

public Course SelectedCourse
{
    get { return selectedCourse; }
    set
    {
        selectedCourse = value;

        // Установить критерий фильтрации для `CoursesStudentsJoinViewModel`
        coursesStudentsJoinViewModel.CourseFilter = selectedCourse;

        // Установить критерий фильтрации для `StudentsViewModel`
        var cSJ = coursesStudentsJoinViewModel.GetCoursesStudentsJoin(selectedCourse);
        this.studentsViewModel.LoadDataUnion(cSJ);

        RaisePropertyChanged(nameof(SelectedCourse));
    }
}

StudentsViewModel

// Students. Все студенты. Заполняется при создании **StudentsViewModel**. 
private ObservableCollection<Student> _students;

public ObservableCollection<Student> Students
{
    get { return _students; }
    set 
    {
        _students = value;
        RaisePropertyChanged(nameof(Students));
    }
}

private ObservableCollection<Student> _studentViews;

// Students. Студенты для представления `CoursesView`
public ObservableCollection<Student> StudentsView
{
    get { return _studentViews; }
    set
    {
        _studentViews = value;
        RaisePropertyChanged(nameof(StudentsView));
    }
}

public void LoadDataUnion(ObservableCollection<CourseStudentJoin> courseStudentJoin)
{
    StudentsView = new ObservableCollection<Student>(Students
                        .Where(cSJ => !courseStudentJoin
                            .Select(s => s.IdStudent).Contains(cSJ.IdStudent)));
}

Ответы (0 шт):