WPF MVVM — WPF и VMMainwindow из моего предыдущего поста для большего контекстаC#

Место общения программистов C#
Anonymous
WPF MVVM — WPF и VMMainwindow из моего предыдущего поста для большего контекста

Сообщение Anonymous »

Я создаю приложение-менеджер рецептов в WPF, используя шаблон MVVM для школьного проекта. Приложение позволяет добавлять новые рецепты через текстовые поля и отображать их в списке.
Каждый рецепт имеет три поля: «Имя», «Категория» и «Калориен». Проект разделен на три отдельных уровня в соответствии со стандартом MVVM — Model, ViewModel и View как отдельные проекты в одном решении.
Базовая функциональность работает нормально. Рецепты загружаются при запуске, в списке они отображаются правильно, а нажатие кнопки «Добавить» создает новый рецепт и добавляет его в список. Текстовые поля ввода также очищаются после нажатия кнопки, что говорит мне о том, что уведомления PropertyChanged работают правильно для свойств ввода в VMMainWindow.
Проблема начинается, когда я выбираю элемент из списка и пытаюсь отобразить его сведения в текстовых блоках ниже. Текстовые блоки привязаны к SelectedRezept.Name, SelectedRezept.Kategorie и SelectedRezept.Kalorien.
При первом выборе они показывают правильные значения, что означает, что сам путь привязки правильный и SelectedRezept установлен правильно.
Однако при запуске метода, который изменяет одно из этих свойств выбранного VMRezept объект, текстовый блок не обновляется. Я могу подтвердить в отладчике, что базовое значение изменяется — пользовательский интерфейс просто не улавливает это.
Отображение обновляется только в том случае, если я нажимаю на другой элемент и затем повторно выбираю исходный, что означает, что WPF не уведомляется об изменении свойства.
Я заметил, что мои установщики в VMRezept вообще не вызывают PropertyChanged — они просто передают значение напрямую в модель. У меня есть вспомогательный метод OnPropertyChanged, определенный в VMRezept, но я никогда его нигде не вызываю. Я не уверен, является ли это основной причиной или реальная проблема заключается в том, что PropertyChanged в дочернем объекте модели представления не перемещается автоматически в родительский VMMainWindow, где находится привязка.
Я попробовал снова запустить PropertyChanged для SelectedRezept из VMMainWindow после вызова метода, и это приводит к обновлению текстовых блоков, но уведомлять об этом кажется неправильным что весь выбранный объект изменился, хотя на самом деле изменилось только одно свойство внутри него.
Мои вопросы:
  • Должен ли каждый установщик в VMRezept вызывать PropertyChanged, даже если значения поступают из уровня модели?
  • Вызывает ли вручную повторный запуск PropertyChanged для SelectedRezept из родительского элемента является стандартным подходом, или существует более чистый шаблон для этого?
  • PropertyChanged в дочерней модели представления когда-либо автоматически распространяется на привязки в родительском элементе, или WPF прослушивает только объект, с которым он непосредственно связан?

    Код: Выделить всё

    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ViewModel
    {
    public class VMMainWindow : INotifyPropertyChanged
    {
    public event PropertyChangedEventHandler? PropertyChanged;
    ObservableCollection rezepteListe;
    VMRezept aktRezept;
    private UserCommand buttonCommand;
    private string neuerName;
    public string NeuerName
    {
    get => neuerName;
    set
    {
    neuerName = value;
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(NeuerName)));
    }
    }
    
    private string neueKategorie;
    public string NeueKategorie
    {
    get => neueKategorie;
    set
    {
    neueKategorie = value;
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(NeueKategorie)));
    }
    
    }
    private int neueKalorien;
    public int NeueKalorien
    { get => neueKalorien;
    set
    {
    neueKalorien = value;
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(NeueKalorien)));
    }
    }
    
    public ObservableCollection RezepteListe { get => rezepteListe; set => rezepteListe = value; }
    public VMRezept AktRezept { get => aktRezept; set => aktRezept = value; }
    public UserCommand ButtonCommand { get => buttonCommand; set => buttonCommand = value; }
    
    public VMMainWindow()
    {
    
    rezepteListe = new ObservableCollection();
    Fuellen();
    this.ButtonCommand = new UserCommand(new Action(VMMWNeuesRezept));
    }
    
    private void VMMWNeuesRezept(object obj)
    {
    VMRezept neuesRezept = new VMRezept(NeuerName, NeueKategorie, NeueKalorien);
    rezepteListe.Add(neuesRezept);
    
    NeuerName = "";
    NeueKategorie = "";
    NeueKalorien = 0;
    }
    
    public void Fuellen()
    {
    RezepteListe.Add(new VMRezept("Pasta Aglio e Olio", "vegetarisch", 400));
    RezepteListe.Add(new VMRezept("Pfannkuchen", "Dessert", 450));
    RezepteListe.Add(new VMRezept("Gulasch", "Hauptgericht", 940));
    }
    
    }
    }
    
    

Вернуться в «C#»