2012-02-07 11 views
5

Gracias a algunos de los consejos que he recibido anteriormente sobre Stack Overflow, he estado haciendo un buen progreso en mi comprensión de MVVM. Sin embargo, es cuando las cosas comienzan a ser más complicadas que todavía estoy luchando.MVVM WPF Master Detail Comboboxes

Tengo la siguiente vista que es con el propósito de ingresar pedidos. Está vinculado a un DataContext de OrderScreenViewModel.

<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> 

El primer cuadro combinado se utiliza para seleccionar un Cliente. El segundo cuadro combinado se utiliza para seleccionar un Código de producto para un nuevo OrderLine.

Hay los artículos que no puedo encontrar la manera de lograr en MVVM:
1) Cuando un cliente se selecciona actualizar los productos de cuadro combinado de modo que su origen de elementos sólo muestra los productos que tienen el mismo identificador de cliente como el CustomerDto registro seleccionado en el cuadro combinado
2) Cuando se llama a Load, establezca SelectedItem en el cuadro combinado Customers para que muestre al Cliente con CustomerId igual al del OrderDto.
3) Aplicar, el mismo proceso que 1) para que solo se muestren/carguen Productos pertenecientes a ese Cliente y establezca SelectedItem en el cuadro combinado Productos para que apunte a la entrada con el mismo ProductId que figura en el OrderLineD a

No estoy seguro de cómo proceder o incluso si tengo las responsabilidades de mis viewmodels correctos. Tal vez tiene algo que ver con NotifyPropertyChanged? Cualquier sugerencia sobre cómo puedo lograr lo anterior será muy apreciada. Estoy seguro de que si lo hago bien, me ayudará mucho en mi aplicación. Muchas gracias 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<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>(); 
     } 
    } 

Respuesta

4

Necesita hacer Productos y Clientes tipo ObservableCollection.

Cuando modifique estas colecciones observables en su modelo de vista, actualizarán la vista, porque las OC ya implementan INotifyPropertyChanged.

Orden y CurrentLine solo debe ser un tipo y realmente no se llama un ViewModel.

1) Tendrá que hacer esto cuando se llame al colocador en el cuadro combinado de SelectedItem del cliente.

2) Deberá hacer esto probablemente en el ctr del OrderScreenViewModel usando su lógica para determinar qué Cliente también debe cambiar el CurrentLine.Customer. Si hace esto en el ctr, esto establecerá el valor antes de que se produzca el enlace.

3) Una vez más, siempre que realice cambios en el ObservableCollection, el cuadro combinado está obligado a, se actualizará la interfaz de usuario. Si realiza un cambio en lo que está obligado el elemento seleccionado, asegúrese de llamar al evento RaisedPropertyChanged.

ETA: Cambiar el xaml a esto, se unen a SelectedProduct y SelectedCustomer de las propiedades selectedItem

<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> 

esto debe empezar en la dirección correcta, todo, toda la lógica para la construcción de los clientes y de los productos por parte del cliente La identificación debe pasar en tus repositorios.

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 
    { 
    } 

Esto es lo que el estándar IRepository parece, esto se llama el patrón Repositorio:

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

Cuando dice LineaActual Orden y deben ser sólo un tipo qué se refiere como OrderDto? Con referencia a 1) eso es lo que pensé que tendría que hacer. Me siento un poco atascado ya que el colocador para el cliente está en WMSOrderViewModel y no tengo ninguna referencia a los productos en OrderScreenViewModel desde aquí. ¿Cómo puedo vincular esos dos elementos? – lostinwpf

+0

Te contactaremos y crearemos un código de ejemplo –

+0

para agregar un código. –