Problem in a ViewModel

Topics: Prism v4 - Silverlight 4
Jul 12, 2012 at 6:34 PM
Edited Jul 12, 2012 at 6:39 PM

I finished my version of UICompositionQuicStart succesfuly, but I have still one problem to solve.

My version uses RIA Services to access Northwind database. My version of EmployeeProjectsViewModel is EmployeeOrdersViewModel which loads the Employee's Orders.

The code that throws the exception is:

public class EmployeeOrdersViewModel : INotifyPropertyChanged {

    NorthwindDomainContext _Context = new NorthwindDomainContext();

    public EmployeeOrdersViewModel() {
        if (!DesignerProperties.IsInDesignTool) {
            EntityQuery queryOrders = _Context.GetOrdersQuery();
            LoadOperation loadOpOrders = _Context.Load(queryOrders);
            loadOpOrders.Completed += new EventHandler(loadOpOrders_Completed);
        }
    }

    void loadOpOrders_Completed(object sender, EventArgs e) {
        if (_Context.Orders.Count != 0) {
            PagedOrders = new PagedCollectionView(_Context.Orders);
        }
    }

    private Employee currentEmployee;
    public Employee CurrentEmployee {
        get {
            return this.currentEmployee;
        }
        set {
            this.currentEmployee = value;

            if (this.CurrentEmployee != null)
                // This instruction throws an exception, When Prism loads this code, it 
                // tries to set the currentEmployee before the LoapOpOrders_Completed is executed 
                // (as a response of a change of the Current Employee in EmployeeListView), which 
                // leads to an exception since PagedOrders is still null.
                this.PagedOrders.Filter = o => ((Order)o).EmployeeID == this.CurrentEmployee.EmployeeID;
            this.PagedOrders.Refresh();

            this.NotifyPropertyChanged("CurrentEmployee");
            this.NotifyPropertyChanged("PagedOrders");
        }
    }

 I don't know how to make it to wait until LoadOpOrders_Completed is executed.

The problem didn't occur in the original since it didn't have to wait for load operations.

Developer
Jul 13, 2012 at 6:06 PM

Hi Rafael,

As a possible approach, I believe you could use a flag to know if the PagedOrders are loaded or not. Then, you could have a isLoadCompleted flag which could be set to false before starting the loading of the orders and set to true in the loadOpOrders_Completed callback. Also, you can check this flag before performing any operation on the PagedOrders property.

As an example, you can check the following code snippet (based on the one you posted above):

public class EmployeeOrdersViewModel : INotifyPropertyChanged {

    private bool isLoadCompleted = false;

    NorthwindDomainContext _Context = new NorthwindDomainContext();

    public EmployeeOrdersViewModel() {
        if (!DesignerProperties.IsInDesignTool) {
            this.isLoadCompleted = false;
            
            EntityQuery queryOrders = _Context.GetOrdersQuery();
            LoadOperation loadOpOrders = _Context.Load(queryOrders);
            loadOpOrders.Completed += new EventHandler(loadOpOrders_Completed);
        }
    }

    void loadOpOrders_Completed(object sender, EventArgs e) {
        if (_Context.Orders.Count != 0) {
            PagedOrders = new PagedCollectionView(_Context.Orders);
        }

        this.isLoadCompleted = true;
        this.FilterPagedOrders(this.CurrentEmployee);
    }

    private Employee currentEmployee;
    public Employee CurrentEmployee {
        get {
            return this.currentEmployee;
        }
        set {
            this.currentEmployee = value;

            this.FilterPagedOrders(value);

            this.NotifyPropertyChanged("CurrentEmployee");
        }
    }

    public void FilterPagedOrders(Employee employee)
    {
        if(isLoadCompleted == true)
        {
            if (employee != null)
                this.PagedOrders.Filter = o => ((Order)o).EmployeeID == employee.EmployeeID;

            this.PagedOrders.Refresh();

            this.NotifyPropertyChanged("PagedOrders");
        }
    }
}

Note that in the aforementioned code snippet, I have moved the filtering of the PagedOrders to a separate method in order to reuse code. However, which implementation you decide to use will depend mostly of your personal preferences and the requirements of your scenario.

I hope you find this useful,

Damian Cherubini
http://blogs.southworks.net/dcherubini

Jul 13, 2012 at 6:18 PM

Thank you Damian.