MVVM WPF主细节combobox

感谢我之前在Stack Overflow上提出的一些建议,我在理解MVVM方面取得了很大的进步。 然而,当事情开始变得更加复杂时,我仍然在苦苦挣扎。

我在下面的视图是为了输入订单。 它绑定到OrderScreenViewModel的DataContext。

    

第一个combobox用于选择客户。 第二个combobox用于为新的OrderLine选择ProductCode。

有些项目我无法解决如何在MVVM中实现:
1)选择客户时更新Productscombobox,以便其项目源仅显示与combobox中选择的CustomerDto记录具有相同CustomerId的产品
2)当调用Load时,在Customerscombobox中设置SelectedItem,以便它显示CustomerId等于OrderDto上的CustomerId。
3)应用与1)相同的过程,以便只显示/加载属于该Customer的产品,并在Productscombobox上设置SelectedItem,使其指向与OrderLineDto中包含的ProductId相同的条目

我不知道如何继续,或者即使我的视图模型的责任是正确的。 也许它与NotifyPropertyChanged有关? 任何有关如何实现上述目标的指示将不胜感激。 我相信如果我做对了,它会对我的应用程序有很大帮助。 非常感谢Alex。

  public class OrderScreenViewModel { public WMSOrderViewModel Order { get; private set; } public WMSOrderLineViewModel CurrentLine { get; private set; } public OrderScreenViewModel() { Order = new WMSOrderViewModel(); CurrentLine = new WMSOrderLineViewModel(new OrderLineDto()); } public void Load(int orderId) { var orderDto = new OrderDto { CustomerId = 1, Lines = new List { new OrderLineDto{ProductId = 1 }} }; Order = new WMSOrderViewModel(orderDto); } public List Customers { get{ return new List { new CustomerDto{CustomerId=1,CustomerCode="Apple"}, new CustomerDto{CustomerId=1,CustomerCode="Microsoft"}, }; } } public List Products { get { return new List { new ProductDto{CustomerId=1,ProductId=1,ProductCode="P100",Description="Pepsi"}, new ProductDto{CustomerId=1,ProductId=2,ProductCode="P110",Description="Coke"}, new ProductDto{CustomerId=2,ProductId=3,ProductCode="P120",Description="Fanta"}, new ProductDto{CustomerId=2,ProductId=4,ProductCode="P130",Description="Sprite"} }; } } public class WMSOrderLineViewModel { private ProductDto _product; private OrderLineDto _orderLineDto; public WMSOrderLineViewModel(OrderLineDto orderLineDto) { _orderLineDto = orderLineDto; } public ProductDto Product { get { return _product; } set{_product = value; RaisePropertyChanged("Product"); } } public class WMSOrderViewModel { private ObservableCollection _lines; private OrderDto _orderDto; public ObservableCollection Lines { get { return _lines; } } private CustomerDto _customer; public CustomerDto Customer { get{return _customer;} set{_customer =value; RaisePropertyChanged("Customer") } public WMSOrderViewModel(OrderDto orderDto) { _orderDto = orderDto; _lines = new ObservableCollection(); foreach(var lineDto in orderDto.Lines) { _lines.Add(new WMSOrderLineViewModel(lineDto)); } } public WMSOrderViewModel() { _lines = new ObservableCollection(); } } 

您需要使产品和客户键入ObservableCollection。

当您在viewmodel中更改这些observablecollections时,它们将更新视图,因为OC已经实现了INotifyPropertyChanged。

Order和CurrentLine应该只是一种类型而不是真正被称为ViewModel。

1)当选择Customercombobox的SelectedItem上调用setter时,你将不得不这样做。

2)您可能需要在OrderScreenViewModel的ctr中执行此操作,方法是使用您的逻辑来确定Customer还要更改CurrentLine.Customer。 如果在ctr中执行此操作,则会在绑定发生之前设置该值。

3)同样,只要你对combobox绑定的ObservableCollection进行更改,它就会更新UI。 如果您对SelectedItem绑定的内容进行了更改,请确保调用RaisedPropertyChanged事件。

ETA:将xaml更改为this,绑定到SelectedItem属性的SelectedProduct和SelectedCustomer

     

这应该让您开始朝着正确的方向前进,一切都是由客户ID构建客户和产品的所有逻辑都需要在您的存储库中进行。

  public class OrderScreenViewModel : INotifyPropertyChanged { private readonly IProductRepository _productRepository; private readonly ICustomerRepository _customerRepository; public OrderScreenViewModel(IProductRepository productRepository, ICustomerRepository customerRepository) { _productRepository = productRepository; _customerRepository = customerRepository; BuildCustomersCollection(); } private void BuildCustomersCollection() { var customers = _customerRepository.GetAll(); foreach (var customer in customers) _customers.Add(customer); } private ObservableCollection _customers = new ObservableCollection(); public ObservableCollection Customers { get { return _customers; } private set { _customers = value; } } private ObservableCollection _products = new ObservableCollection(); public ObservableCollection Products { get { return _products; } private set { _products = value; } } private Customer _selectedCustomer; public Customer SelectedCustomer { get { return _selectedCustomer; } set { _selectedCustomer = value; PropertyChanged(this, new PropertyChangedEventArgs("SelectedCustomer")); BuildProductsCollectionByCustomer(); } } private Product _selectedProduct; public Product SelectedProduct { get { return _selectedProduct; } set { _selectedProduct = value; PropertyChanged(this, new PropertyChangedEventArgs("SelectedProduct")); DoSomethingWhenSelectedPropertyIsSet(); } } private void DoSomethingWhenSelectedPropertyIsSet() { // elided } private void BuildProductsCollectionByCustomer() { var productsForCustomer = _productRepository.GetById(_selectedCustomer.Id); foreach (var product in Products) { _products.Add(product); } } public event PropertyChangedEventHandler PropertyChanged = delegate { }; } public interface ICustomerRepository : IRepository { } public class Customer { public int Id { get; set; } } public interface IProductRepository : IRepository { } public class Product { } 

这是标准IRepository的样子,这称为存储库模式:

  public interface IRepository { IEnumerable GetAll(); T GetById(int id); void Save(T saveThis); void Delete(T deleteThis); }