Prism-MVVM-EF: Master-Details Relationship using Navigation Property

Topics: Prism v4 - WPF 4
Feb 3, 2013 at 8:43 AM
Edited Feb 4, 2013 at 9:25 AM
Firstly, sorry for this long question but it is very critical to my LOB application and i hope you will
     have patience with me here
I will use Customer - Order - OrderDetail as analogy to my system.
My Target: is to build CustomerDetailsView (wpf user control) containing single Customer Details as master in the upper part of the view and in lower part of same view TabControl containing multiple TabItems: Orders tab, Addresses Tab, ... as slaves for that displayed customer.(this sequence will be repeated with Order - OrderDetail- ...)

Now to the details:

1-In the database
i have Customer table that has one-to-many relationship with
Oreder table (Customer is the parent and orders are childern) and OrderDetail table
where Order has one-to-many relationship with OrderDetail.

2-In the EDM
i have Customer entity contains navigation property Orders with Order entity
and Order entity has navigation property OrderDetails with OrederDetail entity

3-In the Model:
now the Customer model class contains this relationship to Order model class:
     public IEnumerable<Order> Orders { get; set; }
and Order model class contains relationship to orderDetail:
     public IEnumerable<OrderDetail> OrderDetails { get; set; } 
*all model classes are populated from entities using services

4-In ViewModel (CustomerDetailsViewModel)
every model property is mirrored to view model and that properties are populated from the model.
the view model will have many views : the CustomerDetailsView and the UserControls that will contain the DataGrids and reside in the tabControl that will reside in CustomerDetailsView
The property that represents the navigation property i mirrored in view model
like this:
    private ObservableCollection<Order> _orders;
    public ObservableCollection<Order> Orders
    {
        get
        {

            return _customer.Orders.ToObservableCollection(); //_customer is the model object
        }

        set
        {

            if (_orders != value)
            {
                _orders = value;
                PropertyChanged(this, new PropertyChangedEventArgs("Orders"));
            }

        }

    }
5-In View (CustomerDetailsView ):
in the lower part with multiple taps (as explained above), each tab will contain DataGrid view that will contains slaves Data Orders, Addresses, ...
in xaml of
             <DataGrid ItemsSource="{Binding Orders}" 
                       AutoGenerateColumns="False" 
                       ....
My Questions:
1-Is this the right approach to represent navigation property as collection in Model, ViewModel?
2-Is the right way to use ObservableCollection<OrderViewModel> _orders instead of
   ObservableCollection<Order> _orders in CustomerDetailsViewModel to represent collection of orders
   i.e. using one view model for master and slave or using two view models?
3-Is there sample application that model this scenarion w/o violating MVVM , Prism, MEF rules?
4-Is this the right way to mirror such hierarchy in the real world and model the Master-Slave relationship?
many questions to come after answering these first three.
Many thanks in advance for your time and help.
Developer
Feb 4, 2013 at 9:03 PM
Edited Feb 4, 2013 at 9:03 PM
Hi there,

Sorry for the delay, but after analyzing the scenario you described, I realized that a recommended approach that could be used for this kind of scenarios, could be like the one used in the UI Composition QuickStart provided with Prism , which so far is the only sample I know, that illustrates a similar scenario like the one you described.

As you may find this approach, could be useful to keep a clean separation on the different layers of your application. Also, it uses different view models for each of the details views in order to represent the information from the currently selected Exployee which for example in your case could be the selected customer , this approach in my opinion will result in a cleaner one than only having only one view model.

Although, this sample was built with Unity and Silverlight I believe you could find the concepts explained there useful to tackle your application as a similar approach could be used in a WPF application without problems.

I hope you find this as a helpful reference to start with,

Regards,

Agustin Adami
http://blogs.southworks.net/aadami
Feb 5, 2013 at 6:00 PM
Edited Feb 5, 2013 at 6:16 PM
Hi,
Sorry adami this is not my case and not my goal.
My goal is how to mirror the master details relationship or the hierarchy exist in real work into my application, starting from
the database (foreign keys) to EDM (navigation property) to Service (detail is collection inside the master service) to Model (detail is collection of models inside the master model) to View Model (detail is a collection of models or ViewModel inside the master view model) up to the view where different details views are contained in several tabs nested inside the master user control. then i should be able to apply CRUD operations on these details tables. I don't know how to do this w/o violating Prism and MVVM rules.
To be more specific my problem is how to model the master - details relationship in the view model in conformance
with Prism and MVVM rules and allowing CRUD operations in details views withing master view?
sorry if i can't explain my target clearly.
Developer
Feb 6, 2013 at 7:11 PM
Edited Feb 6, 2013 at 7:12 PM
Hi,

As far as I know there are no examples or guidance of how to connect or update a back-end database in the Prism, I believe this is mainly because this guidance is focused on the presentation layer and not how you architect your Business Logic Layer or Data Access Layer. And this is why there are no Quick starts related to this. However, if you believe this should be changed, you could copy this as a work-item in the issue tracker section , so the P&P team can analyze this for future releases.

On the other hand, I believe you could check some of the samples suggested in this thread where a similar topic was discussed, perhaps you could find them useful to tackle your scenario:
Additionally, you may also find the new upcoming release from the P&P team named Kona interesting, although it is in its first drops, it will will provide written guidance and a reference implementation that describe recommended practices for building LOB Windows 8 client apps using WinRT and .NET.

Best Regards,

Agustin Adami
http://blogs.southworks.net/aadami
Feb 6, 2013 at 9:42 PM
Edited Feb 6, 2013 at 9:50 PM
Hi Adami'
Thanks for trying to help.
I found a solution to implement master details hierarchy in the View Model part but i want
your help to make it work and make it conform with Prism-MEF (this solution for Ryan Vice)

Now down to the trenches:

*CustomerDetailsView.xaml is the view that will contain Master (Customer) data and Details
(Order, Addresses ...) data in tabitems nested inside CustomerDetailsView.xaml
*CustomerDetailsViewModel.cs : is the View Model for previous view
*Now to add Order as details to to master customer in CustomerDetailsView.xaml view:

1-Add class OrderViewModel:
 public class OrderViewModel
 {
   private Order _model;
   public Order Model
 {
   get { return _model; }
   set
    {
      if (_model == value)
      return;
      _model = value;
      RaisePropertyChanged(ModelPropertyName);
     }
  }

  public OrderViewModel(Order model)
  {
    _model = model;
    
  }
2-Add class called OrdersViewModel.cs This View Model takes a collection of Model.Order (Order model )
objects as a constructor argument and then exposes them as a collection
of OrderViewModel instances for consumption by the view.
    public class OrdersViewModel
    {
       public ObservableCollection<OrderViewModel>
               Orders { get; set; }
      public OrdersViewModel(
               IEnumerable<Model.Order> orders)
       {
         Orders = new ObservableCollection<OrderViewModel>(
         orders.Select(o => new OrderViewModel(o)));
       }
     }
3-in CustomerDetailsViewModel.cs add the following property to it. This property is lazy instantiated and when its getter
is called it will create a new OrderViewModel, if one hasn't been created, and pass it to Customers.Orders.
   private OrdersViewModel _orders;
   public OrdersViewModel Orders
   {
     get
       {
         if (Customer == null)
         return null;
         return _orders ?? (_orders
                = new OrdersViewModel(Customer.Orders));
        }
    }
Now we have CustomerDetailsViewModel contains OrdersViewModel which in turn contains
a collection of OrderViewModels which implement the hierarchy

4-Create OrdersView.xaml with OrdersViewModel.cs as its view model

OrdersView.xaml will contain datagrid with
ItemsSource="{Binding Orders}"  
(Orders here is the ObservableCollection<OrderViewModel> contained in OrdersViewModel) hence it will display grid of orders

5-in CustomerDetailsView.xaml in the tabitem that will contain orders we bind it to the OrdersViewModel in CustomerDetailsViewModel.cs
  <ContentControl Content="{Binding Orders}" /> 
(Orders here is the OrdersViewModel property contained in CustomerDetailsViewModel )


**{this may help: Adami created spike "TabControlDynamicTabItems" in previous thread "prism: problems with dynamically adding tabitems"
if you replaced SubsystemDetailsViewModel by CustomerDetailsViewModel and SubsystemDetailsView by CustomerDetailsView it will be our case }
**Now I need to involve MEF + make this code work (i tried but it is not working)+make this code compliant
with Prism

**You help is very much appreciated.