将项添加到模型 C# wpf 时更新可观察集合

本文关键字:更新 观察 集合 wpf 添加 模型 | 更新日期: 2023-09-27 18:31:36

好的,所以我对此相当陌生。我遵循了YouTube上的这个MVVM教程。这是相当不错和直接的。基本上,它设置了一个非常基本的程序,其中包含一个模型类,DataAcess类,3个视图模型(主窗口,员工和ViewModelBase),最后是一个视图,该视图具有堆栈面板和几个文本框,这些文本框绑定到模型中的FirstName和LastName。

这一切都按照它的意思工作,我已经经历过很多次了,我很确定我理解它是如何工作的,但我遇到的麻烦是增加新员工

在 DataAccess 类(员工存储库)中,将按如下所示添加员工。

    class EmployeeRepository
{
    readonly List<Employee> _employee;
    public EmployeeRepository()
    {
        if (_employee == null)
        {
            _employee = new List<Employee>();
        }
        _employee.Add(Employee.CreateEmployee("Bob", "Jones"));
        _employee.Add(Employee.CreateEmployee("Sarah", "Marshall"));
        _employee.Add(Employee.CreateEmployee("Peter", "Piper"));
    }
    public List<Employee> GetEmployees()
    {
        return new List<Employee>(_employee);
    }

}

在模型中有一个方法调用 CreateEmployee

    public class Employee
{
    public static Employee CreateEmployee(string firstName, string lastName)
    {
        return new Employee { FirstName = firstName, LastName = lastName };
    }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

所以我想我会在主窗口中添加一个按钮,然后在列表中添加另一个名称。跳跃视图将随着项目的更新而更新。只是为了看看它是否有效,我只是使用了后面的代码。

我想我可以像在 EmployeeRepository 中一样添加一个新员工,所以我尝试了这个

    readonly List<Employee> _employee = new List<Employee>();
    private void btnAdd_Click(object sender, RoutedEventArgs e)
    {
        _employee.Add(Employee.CreateEmployee("John", "Smith"));
    }

我已经尝试了很多方法,但无济于事。我看过并阅读了许多教程和问题,但我尝试过的任何内容都没有奏效。

我错过了什么?我最初认为它不起作用,因为我将项目添加到存储库中的列表中,而不是添加到视图模型中的可观察集合中。AllEmployees ObservableCollection 是供查看的 ItemSource。

    readonly EmployeeRepository _employeeRepository;
    public ObservableCollection<Model.Employee> AllEmployees
    {
        get;
        private set;
    }
    public EmployeeListViewModel(EmployeeRepository currentWindowRepository)
    {
        if (currentWindowRepository == null)
        {
            throw new ArgumentException("currentWindowRepository");
        }
        _employeeRepository = currentWindowRepository;
        this.AllEmployees = new ObservableCollection<Model.Employee>(_employeeRepository.GetEmployees());
    }

但是在按钮代码中,我尝试实现类似的东西,但没有。

我还可以添加视图 xaml 代码和 MainViewModel 代码,以便您可以根据需要查看它们是如何绑定的。

提前感谢任何帮助!

将项添加到模型 C# wpf 时更新可观察集合

你不能在"一个操作"中做到这一点。

在 UI 中添加新Employee时,首先需要实例化Employee类并将其添加到可观察集合中。

如果处于有效状态,则将其保存到存储库中。

private ICommand addEmployeeCommand;
public ICommand AddEmployeeCommand { get { return addEmployeeCommand; } }
public ObservableCollection<Employee> Employees { get; protected set; }
private void AddEmployee() 
{
    // Get the user input that's bound to the viewmodels properties
    var employee = Employee.Create(FirstName, LastName);
    // add it to the observable collection
    // Note: directly using model in your ViewModel for binding is a pretty bad idea, you should use ViewModels for your Employees too, like: 
    // Employee.Add(new EmployeeViewModel(employee));
    Employees.Add(employee);
    // add it to the repository
    this.employeeRepository.AddOrUpdate(employee);
}
// in constructor
this.addEmployeeCommand = new DelegateCommand(AddEmployee, CanExecuteAddEmployee);

如前所述,避免在 ViewModel 绑定中直接使用模型,它有几个缺点,就像您现在的视图依赖于您的视图模型一样。 模型中的每一个变化都需要反映在视图中,这超过了视图模型的目的,该视图模型旨在分离视图,视图模型和模型。

另一个缺点是,通常您的模型不会实现INotifyPropertyChanged这将导致视图中的内存泄漏。

在您的 EmployeelistViewModel 中,您正在创建 ObservableCollection ,并且您认为它会在添加/删除员工时自动重新填充。 其次,在GetEmployees方法中,您正在创建一个新列表。 您应该直接使用 obser.coll 代替 List (_employee)。并从您的方法中返回此 ocoll。

一种解决方案是将 INPC 添加到您的模型中,然后让您的视图模型观察它们的模型并相应地更新自己,即如下所示:

public class MyListType
{
    // some data
}
public class MyModel
{
    public IList<MyListType> MyListItems { get; set; }
    public MyModel()
    {
        this.MyListItems = new ObservableCollection<MyListType>();
    }
}
public class MyListTypeViewModel : ViewModelBase
{
    public MyListType Model {get; set;}
    // INPC properties go here
}
public class MyViewModel
{
    public IList<MyListTypeViewModel> MyListItemViewModels { get; set; }
    public MyViewModel(MyModel model)
    {
        (model.MyListItems as INotifyCollectionChanged).CollectionChanged += OnListChanged;
        // todo: create initial view models for any items already in MyListItems
    }
    private void OnListChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        // create any new elements
        if (e.NewItems != null)
            foreach (MyListType item in e.NewItems)
                this.MyListItemViewModels.Add(new MyListTypeViewModel{Model = item});
        // remove any new elements
        if (e.OldItems != null)
            foreach (MyListType item in e.OldItems)
                this.MyListItemViewModels.Remove(
                    this.MyListItemViewModels.First(x => x.Model == item)
                );
    }

现在,您的视图模型列表将自动与您的模型列表保持同步。这种方法的主要问题是,您的模型通常来自您的ORM(数据库)代码,因此您需要使用在创建时用于注入INPC的任何框架,例如,如果您使用的是NHibernate,那么您需要使用INPC的绑定拦截器和集合约定来使列表ObservableCollections。