将项添加到模型 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 代码,以便您可以根据需要查看它们是如何绑定的。
提前感谢任何帮助!
你不能在"一个操作"中做到这一点。
在 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。