WPF Datagrid не обновляется при вызове SaveChange() в Entity Framework

Вопрос или проблема

У меня есть небольшое приложение WPF / .NET, соединенное с базой данных SQLite через System.Data.Entity. В MainWindow есть кнопка и текстовое поле. Когда кнопка нажата, новый элемент с id должен быть добавлен в базу данных. Это работает и обновляет dataGrid правильно. Но если элемент с текущим id уже существует, вместо этого должно увеличиваться значение count. Эти изменения правильно применяются к базе данных, но не к data grid. Значение в dataGrid обновляется только тогда, когда я прокручиваю вниз, пока он не скрывается, а затем снова появляются. Как я могу это правильно исправить?

Код MainWindow.xaml.cs выглядит следующим образом:

public partial class MainWindow : Window
{
    private ProductContext _context;

    public MainWindow()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Product newProduct = new Product() {
            Id = idTextBox.Text,
            Count = 1
        };

        Product oldProduct = _context.Products.Find(newProduct.Id);
        if(oldProduct!= null)
            oldProduct.Count++;
        else
            _context.Products.Add(newProduct);

        _context.SaveChanges();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        _context = new ProductContext();

        _context.Products.Load();
        dataGrid.ItemsSource = _context.Products.Local;
    }

    private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
    {
        _input.Dispose();
    }
}

Код DataGrid в MainWindow.xaml:

<DataGrid AutoGenerateColumns="False" Name="dataGrid">
    <DataGrid.Columns>
        <DataGridTextColumn Header="ID" Binding="{Binding Id}"/>
        <DataGridTextColumn Header="COUNT" Binding="{Binding Count}"/>
    </DataGrid.Columns>
</DataGrid>

Контекст базы данных:

public partial class ProductContext : DbContext
{
    public DbSet<Product> Products { get; set; }

    public ProductContext () : base("name=ProductDB") { }
}

Продукт:

public class Product
{
    public string Id { get; set; }
    public int Count { get; set; }
}

Я пробовал добавлять _context.Products.Load() и несколько других неудачных вариантов, но ничего не изменилось.

П.С. Я буду очень признателен за совет, если я принципиально делаю что-то неправильно при взаимодействии с базой данных

Ответ или решение

Чтобы ваш WPF DataGrid корректно обновлялся после изменения значений в вашей базе данных, вам необходимо убедиться, что изменения, примененные к объектам в контексте Entity Framework, извлекаются и отражаются в привязанном источнике данных. В вашем случае, проблема заключается в том, что DataGrid не обновляется автоматически, когда учётные записи уже существуют и вы увеличиваете значение поля Count.

Проблема, с которой вы столкнулись, связана с тем, что ObservableCollection или аналогичная структура данных может лучше поддерживать уведомления об изменениях. Давайте рассмотрим, как можно это исправить.

Решение

  1. Используйте ObservableCollection:
    Замените локальную коллекцию на ObservableCollection. Это обеспечит, что любые изменения будут автоматически отражаться в DataGrid.

  2. Используйте интерфейс INotifyPropertyChanged:
    Убедитесь, что ваш класс Product реализует INotifyPropertyChanged, чтобы обеспечить уведомления об изменении свойств.

Вот обновлённый код вашего класса Product и изменённый код в MainWindow.xaml.cs.

Класс Product

using System.ComponentModel;

public class Product : INotifyPropertyChanged
{
    private string _id;
    private int _count;

    public string Id
    {
        get => _id;
        set
        {
            _id = value;
            OnPropertyChanged(nameof(Id));
        }
    }

    public int Count
    {
        get => _count;
        set
        {
            _count = value;
            OnPropertyChanged(nameof(Count));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Класс MainWindow

using System.Collections.ObjectModel;
using System.Data.Entity;
using System.Windows;

public partial class MainWindow : Window
{
    private ProductContext _context;
    private ObservableCollection<Product> _products;

    public MainWindow()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        string productId = idTextBox.Text;

        Product oldProduct = _context.Products.Find(productId);
        if (oldProduct != null)
        {
            oldProduct.Count++;
            // Вызовите метод для уведомления об изменениях
            _context.Entry(oldProduct).State = EntityState.Modified;
        }
        else
        {
            Product newProduct = new Product()
            {
                Id = productId,
                Count = 1
            };
            _context.Products.Add(newProduct);
            _products.Add(newProduct); // добавляем в ObservableCollection
        }

        _context.SaveChanges();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        _context = new ProductContext();
        _products = new ObservableCollection<Product>(_context.Products.Local.ToList());
        dataGrid.ItemsSource = _products;

        _context.Products.Load(); // Загружаем данные из базы данных
    }

    private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
    {
        _context.Dispose();
    }
}

Объяснение изменений:

  1. ObservableCollection: Вместо того, чтобы использовать Local, мы создаем новую экземпляр ObservableCollection и привязываем его к DataGrid. Это позволяет автоматически обновлять интерфейс при изменении коллекции.

  2. INotifyPropertyChanged: Реализация интерфейса INotifyPropertyChanged в вашем классе Product позволяет уведомлять интерфейс о том, что свойство изменилось, что приводит к его автоматическому обновлению в DataGrid.

  3. Изменение состояния: При увеличении значения Count, мы явно изменяем состояние записи в Entity Framework, чтобы оно стало Modified. Это гарантирует, что изменения будут отслеживаться правильным образом.

Теперь, когда вы обновляете существующий элемент в базе данных, данные в DataGrid будут обновляться корректно и без необходимости прокручивать и скрывать строки.

Попробуйте внести указанные изменения, и ваша проблема должна быть решена.

Оцените материал
Добавить комментарий

Капча загружается...