好的,所以我对此很新。我跟着来自YouTube的this MVVM tutorial。这非常好,直截了当。基本上它使用Model类,DataAcess类,3个viewmodels(主窗口,Employee和ViewModelBase)设置一个非常基本的程序,最后是一个视图,它有一个stackpanel和几个绑定到FirstName和LastName的文本框。模型。
这一切都是有意义的,我经历了很多次,而且我很确定我理解这一切是如何运作的但是我遇到的麻烦就是添加新员工。
在DataAccess类(Employee Repository)中添加了Employees,如下所示。
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; }
}
所以我想我会在MainWindow上添加一个按钮,然后在列表中添加另一个名称。跳转视图将在项目更新时更新。只是为了看看它是否可行我只是使用了背后的代码。
我以为我可以像在EmployeeRepository中那样添加新员工,所以我尝试了这个
readonly List<Employee> _employee = new List<Employee>();
private void btnAdd_Click(object sender, RoutedEventArgs e)
{
_employee.Add(Employee.CreateEmployee("John", "Smith"));
}
我尝试过很多方法,但无济于事。我已经观看并阅读了许多教程和问题,但我没有尝试过任何工作。
我错过了什么?我最初认为它无法正常工作,因为我将项目添加到存储库中的List,而不是添加到viewmodel中的ObservableCollection。 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代码,以便您可以根据需要查看它是如何绑定的。
提前感谢您的帮助!
答案 0 :(得分:1)
您无法在&#34;一次操作&#34;中执行此操作。
在UI中添加新的Employee
时,首先需要实例化Employee
类并将其添加到observable集合中。
如果处于有效状态,则将其保留在存储库中。
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绑定中直接使用您的模型,它有几个缺点,就像您现在查看依赖于您的viewmodel一样。模型中的每一个变化都需要反映在视图中,这超越了视图模型的目的,该视图模型旨在解耦视图,视图模型和模型。
另一个缺点是,通常你的模型没有实现INotifyPropertyChanged
,这会导致视图中的内存泄漏。
答案 1 :(得分:0)
在您的EmployeelistViewModel中,您正在创建ObservableCollection,并且您认为在添加/删除员工时它将自动重新填充。其次,在您的GetEmployees方法中,您将创建一个新列表。你应该直接使用obser.coll代替List(_employee)。并从你的方法返回这个ocoll。
答案 2 :(得分:0)
对此的一个解决方案是将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,那么您需要使用binding interceptor进行INPC,使用collection convention来制作ObservableCollections列表。