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

将项目添加到模型C#wpf时更新可观察集合,c#,wpf,mvvm,binding,observablecollection,C#,Wpf,Mvvm,Binding,Observablecollection,好吧,我对这个还不太熟悉。我跟随YouTube的视频。这是相当好和直接的。基本上,它设置了一个非常基本的程序,其中包含一个模型类、DataAccess类、3个viewmodels(主窗口、Employee和ViewModelBase),最后是一个视图,该视图具有一个stackpanel和两个文本框,这些文本框绑定到模型中的FirstName和LastName 这一切都是按计划进行的,我已经经历了很多次,我很确定我理解这一切是如何进行的,但是我遇到的麻烦是增加新员工 在DataAccess类(Em

好吧,我对这个还不太熟悉。我跟随YouTube的视频。这是相当好和直接的。基本上,它设置了一个非常基本的程序,其中包含一个模型类、DataAccess类、3个viewmodels(主窗口、Employee和ViewModelBase),最后是一个视图,该视图具有一个stackpanel和两个文本框,这些文本框绑定到模型中的FirstName和LastName

这一切都是按计划进行的,我已经经历了很多次,我很确定我理解这一切是如何进行的,但是我遇到的麻烦是增加新员工

在DataAccess类(Employee Repository)中,将添加员工,如下所示

    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);
    }


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

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

    readonly List<Employee> _employee = new List<Employee>();

    private void btnAdd_Click(object sender, RoutedEventArgs e)
    {
        _employee.Add(Employee.CreateEmployee("John", "Smith"));
    }
只读列表_employee=new List();
私有无效btnAdd_单击(对象发送者,路由目标e)
{
_employee.Add(employee.CreateEmployee(“John”、“Smith”));
}
我尝试了很多方法,但都没有成功。我看过很多教程和问题,但没有一个是我尝试过的

我错过了什么?我最初认为它不起作用,因为我正在将该项添加到存储库中的列表中,而不是添加到viewmodel中的ObservableCollection中。AllEmployeesObservableCollection是视图的项目源

    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());
    }
readonly EmployeeRepository\u EmployeeRepository;
公共可观测集合所有员工
{
得到;
私人设置;
}
公共EmployeeListViewModel(EmployeeRepository currentWindowRepository)
{
如果(currentWindowRepository==null)
{
抛出新ArgumentException(“currentWindowRepository”);
}
_employeeRepository=currentWindowRepository;
this.AllEmployees=新的可观察集合(_employeeRepository.GetEmployees());
}
但在按钮代码中,我尝试实现类似的东西,但没有

我还可以添加视图xaml代码和MainViewModel代码,以便您可以查看如何绑定这些代码


提前感谢您的帮助

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

您不能在“一次操作”中完成此操作

在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);
专用ICommand addEmployeeCommand;
public ICommand AddEmployeeCommand{get{return AddEmployeeCommand;}}
公共ObservableCollection雇员{get;protected set;}
私人雇员()
{
//获取绑定到viewmodels属性的用户输入
var employee=employee.Create(FirstName,LastName);
//将其添加到可观察集合中
//注意:在ViewModel中直接使用model进行绑定是一个非常糟糕的主意,您也应该为员工使用ViewModels,例如:
//Employee.Add(新建EmployeeViewModel(Employee));
Employees.Add(Employees);
//将其添加到存储库中
this.employeeRepository.AddOrUpdate(employee);
}
//在构造函数中
this.addEmployeeCommand=新的DelegateCommand(AddEmployee,CanExecuteAddEmployee);
如前所述,避免在ViewModel绑定中直接使用模型,它有几个缺点,比如现在视图依赖于ViewModel。模型中的每一个更改都需要反映在视图中,这超出了viewmodel的目的,viewmodel旨在解耦视图、viewmodel和模型


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

解决方案之一是将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)
                );
    }
公共类MyListType
{
//一些数据
}
公共类MyModel
{
公共IList MyListItems{get;set;}
公共MyModel()
{
this.MyListItems=新的ObservableCollection();
}
}
公共类MyListTypeViewModel:ViewModelBase
{
公共MyListType模型{get;set;}
//INPC属性在这里
}
公共类MyViewModel
{
公共IList MyListItemViewModels{get;set;}
公共MyViewModel(MyModel模型)
{
(model.MyListItems作为INotifyCollectionChanged)。CollectionChanged+=OnListChanged;
//todo:为MyListItems中已有的任何项目创建初始视图模型
}
private void OnListChanged(对象发送方,NotifyCollectionChangedEventArgs e)
{
//创建任何新元素
如果(如NewItems!=null)
foreach(e.NewItems中的MyListType项)
this.MyListItemViewModels.Add(新的MyListTypeViewModel{Model=item});
//删除任何新元素
如果(例如,OldItems!=null)
foreach(e.OldItems中的MyListType项)
this.MyListItemViewModels.Remove(
首先(x=>x.Model==item)
);
}
现在,视图模型列表将自动与模型列表保持同步。这种方法的主要问题是,模型通常源于ORM(数据库)代码,因此您需要在创建时使用任何框架注入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)
                );
    }