C# MVVM WPF主详细信息组合框

C# MVVM WPF主详细信息组合框,c#,wpf,mvvm,combobox,prism,C#,Wpf,Mvvm,Combobox,Prism,多亏了我之前得到的一些关于堆栈溢出的建议,我在理解MVVM方面取得了很好的进展。然而,当事情开始变得更加复杂时,我仍然在挣扎 我有以下视图,用于输入订单。它绑定到OrderScreenViewModel的DataContext <StackPanel> <ComboBox Height="25" Width="100" DisplayMemberPath="CustomerCode" SelectedItem="{Binding Path=Order.Customer}

多亏了我之前得到的一些关于堆栈溢出的建议,我在理解MVVM方面取得了很好的进展。然而,当事情开始变得更加复杂时,我仍然在挣扎

我有以下视图,用于输入订单。它绑定到OrderScreenViewModel的DataContext

<StackPanel>
    <ComboBox Height="25" Width="100" DisplayMemberPath="CustomerCode" SelectedItem="{Binding Path=Order.Customer}" ItemsSource="{Binding Path=Customers}"></ComboBox>
    <ComboBox Height="25" Width="100" DisplayMemberPath="ProductCode" SelectedItem="{Binding Path=CurrentLine.Product}" ItemsSource="{Binding Path=Products}"></ComboBox>
</StackPanel>

第一个组合框用于选择客户。第二个组合框用于为新订单行选择ProductCode

有一些我无法在MVVM中实现的项目:
1)选择客户时,更新产品组合框,使其项目源仅显示与组合框中选择的客户具有相同客户ID的产品
2)调用Load时,在Customers(客户)组合框中设置SelectedItem,使其显示CustomerId等于OrderDto上的CustomerId的客户。
3)应用,与1)相同的过程,以便仅显示/加载属于该客户的产品,并在“产品”组合框上设置SelectedItem,使其指向与OrderLineDto中包含的产品ID相同的条目

我不知道如何继续,甚至不知道我的viewmodels的职责是否正确。也许这与NotifyPropertyChanged有关?任何关于我如何实现上述目标的建议都将不胜感激。我相信,如果我做对了,这将对我的应用程序有很大帮助。非常感谢亚历克斯

 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<OrderLineDto> { new OrderLineDto{ProductId = 1 }} };
            Order = new WMSOrderViewModel(orderDto);
        }

        public List<CustomerDto> Customers
        {
            get{
                return new List<CustomerDto> { 
                        new CustomerDto{CustomerId=1,CustomerCode="Apple"},
                        new CustomerDto{CustomerId=1,CustomerCode="Microsoft"},
                };
            }
        }

        public List<ProductDto> Products
        {
            get
            {
                return new List<ProductDto> { 
                    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<WMSOrderLineViewModel> _lines;
        private OrderDto _orderDto;
        public ObservableCollection<WMSOrderLineViewModel> 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<WMSOrderLineViewModel>();
            foreach(var lineDto in orderDto.Lines)
            {
                _lines.Add(new WMSOrderLineViewModel(lineDto));
            }
        }

        public WMSOrderViewModel()
        {
            _lines = new ObservableCollection<WMSOrderLineViewModel>();
        }
    }
公共类OrderScreenViewModel
{
公共WMSOrderViewModel顺序{get;private set;}
public WMSOrderLineViewModel CurrentLine{get;private set;}
public OrderScreenViewModel()
{
订单=新的WMSOrderViewModel();
CurrentLine=new WMSOrderLineViewModel(new OrderLineDto());
}
公共无效加载(int orderId)
{
var orderDto=new orderDto{CustomerId=1,line=new List{new OrderLineDto{ProductId=1}};
订单=新的WMSOrderViewModel(orderDto);
}
公开名单客户
{
得到{
返回新列表{
新CustomerTo{CustomerId=1,CustomerCode=“Apple”},
新CustomerTo{CustomerId=1,CustomerCode=“Microsoft”},
};
}
}
公开上市产品
{
得到
{
返回新列表{
新产品DTO{CustomerId=1,ProductId=1,ProductCode=“P100”,Description=“Pepsi”},
新产品DTO{CustomerId=1,ProductId=2,ProductCode=“P110”,Description=“Coke”},
新产品DTO{CustomerId=2,ProductId=3,ProductCode=“P120”,Description=“Fanta”},
新产品DTO{CustomerId=2,ProductId=4,ProductCode=“P130”,Description=“Sprite”}
};
}
}
公共类WMSOrderLineViewModel
{
私人产品;私人产品;
私人OrderLineDto_OrderLineDto;
公共WMSOrderLineViewModel(OrderLineDto OrderLineDto)
{
_orderLineDto=orderLineDto;
}
公共产品到产品{get{return\u Product;}
设置{u product=value;RaisePropertyChanged(“product”);}
}
公共类WMSOrderViewModel
{
私人可观测采集线;
私人订单到(u OrderDto);;
公共可观测收集行{get{return\u Lines;}}
私人客户对客户;
public CustomerDto Customer{get{return{u Customer;}set{{u Customer=value;RaisePropertyChanged(“客户”)}
公共WMSOrderViewModel(OrderDto OrderDto)
{
_orderDto=orderDto;
_行=新的ObservableCollection();
foreach(orderDto.Lines中的变量lineDto)
{
_添加(新的WMSOrderLineViewModel(lineDto));
}
}
公共WMSOrderViewModel()
{
_行=新的ObservableCollection();
}
}

您需要让产品和客户输入ObservableCollection

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

Order和CurrentLine应该只是一种类型,而不是真正的ViewModel

<StackPanel>
    <ComboBox Height="25" Width="100" DisplayMemberPath="CustomerCode" SelectedItem="{Binding Path=Order.Customer}" ItemsSource="{Binding Path=Customers}"></ComboBox>
    <ComboBox Height="25" Width="100" DisplayMemberPath="ProductCode" SelectedItem="{Binding Path=CurrentLine.Product}" ItemsSource="{Binding Path=Products}"></ComboBox>
</StackPanel>
1) 当在Customer组合框的SelectedItem上调用setter时,必须执行此操作

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

3) 同样,只要您更改组合框绑定到的ObservableCollection,它就会更新UI。如果您更改SelectedItem绑定的内容,只需确保调用RaisedPropertyChanged事件即可

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

<StackPanel>
    <ComboBox Height="25" Width="100" DisplayMemberPath="CustomerCode" SelectedItem="{Binding Path=SelectedCustomer}" ItemsSource="{Binding Path=Customers}"></ComboBox>
    <ComboBox Height="25" Width="100" DisplayMemberPath="ProductCode" SelectedItem="{Binding Path=SelectedProduct}" ItemsSource="{Binding Path=Products}"></ComboBox>
</StackPanel>

这应该让您朝着正确的方向开始,在您的存储库中,所有根据客户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<Customer> _customers = new ObservableCollection<Customer>();
      public ObservableCollection<Customer> Customers
      {
         get { return _customers; }
         private set { _customers = value; }
      }

      private ObservableCollection<Product> _products = new ObservableCollection<Product>();
      public ObservableCollection<Product> 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<Customer>
   {
   }

   public class Customer
   {
      public int Id { get; set; }
   }

   public interface IProductRepository : IRepository<Product>
   {
   }

   public class Product
   {
   }
公共类OrderScreenViewModel:INotifyPropertyChanged
{
私有只读IPProductRepository\u productRepository;
专用只读ICCustomerRepository\u customerRepository;
public OrderScreenViewModel(IPProductRepository productRepository,
ICCustomerRepository(客户存储库)
{
_productRepository=productRepository;
_customerRepository=customerRepository;
buildCustomerCollection();
}
私有void builderCustomerCollection()
{
var customers=_customerRepository.GetAll();
外汇