Click here to Skip to main content
15,881,852 members
Articles / Programming Languages / C#

Migrate from Basic to MVVM and MEF Composable Patterns for a Silverlight Application - Part 3

Rate me:
Please Sign up or sign in to vote.
5.00/5 (4 votes)
3 May 2012CPOL12 min read 24.7K   464   9  
The article series shows how to upgrade a Silverlight application having basic patterns to the MVVM and MEF composable patterns with easy approaches and detailed coding explanations.
using System;
using System.Windows;
using System.Linq;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Primitives;
using System.Collections.ObjectModel;
using ProductRiaLib.Web.Services;
using ProductRiaLib.Web.Models;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using ProductApp.Common;


namespace ProductApp.ViewModels
{
    [Export(typeof(IModule)), ExportMetadata(MetadataKeys.Name, ModuleID.ProductListViewModel)]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class ProductListViewModel : ViewModelBase, IModule
    {        
        private IProductListModel _productListModel;
        private Category _comboDefault = new Category { CategoryID = -1, CategoryName = "Please Select" };
        
        public ProductListViewModel()
        {
            // Inject the Model as the Lazy object with the defined type
            _productListModel = ModuleCatalogService.Container.GetExport<IProductListModel>(ModuleID.ProductListModel).Value;
           
            // Register the event handlers defined in the Model            
            _productListModel.GetCategoryLookupComplete += ProductListModel_GetCategryComplete;
            _productListModel.GetCategorizedProductsComplete += ProductListModel_GetCategorizedProductComplete;
            _productListModel.SaveChangesComplete += ProductListModel_SaveChangesComplete;

            // Register message handler
            Messenger.Default.Register(this, MessageToken.DataToProductListVmMessage, new Action<Product>(OnDataToProductListVmMessage));

            // Get data for Category dropdown list
            _productListModel.GetCategoryLookup();
        }       

        private ObservableCollection<Category> _categoryItems;
        //
        public ObservableCollection<Category> CategoryItems
        {
            get { return _categoryItems; }
            private set
            {
                if (!ReferenceEquals(_categoryItems, value))
                {
                    _categoryItems = value;
                    RaisePropertyChanged("CategoryItems");
                }
            }
        }

        private Category _selectedCategory;
        //
        public Category SelectedCategory
        {
            get { return _selectedCategory; }
            set
            {
                if (!ReferenceEquals(_selectedCategory, value))
                {
                    _selectedCategory = value;
                    RaisePropertyChanged("SelectedCategory");
                }
            }
        }
        
        private ObservableCollection<Product> _productItems;
        //
        public ObservableCollection<Product> ProductItems
        {
            get { return _productItems; }
            private set
            {
                if (!ReferenceEquals(_productItems, value))
                {
                    _productItems = value;
                    RaisePropertyChanged("ProductItems");
                }
            }
        }

        private Product _currentProduct;
        //-->
        public Product CurrentProduct
        {
            get { return _currentProduct; }
            set
            {
                if (!ReferenceEquals(_currentProduct, value))
                {
                    _currentProduct = value;
                    RaisePropertyChanged("CurrentProduct");
                }
            }
        }

        private RelayCommand _categorySelectionChanged;
        //
        public RelayCommand CategorySelectionChanged
        {
            get
            {
                if (_categorySelectionChanged == null)
                {
                    _categorySelectionChanged = new RelayCommand(
                        OnCategorySelectionChanged,
                        () => true);
                }
                return _categorySelectionChanged;
            }
        }
        //
        private void OnCategorySelectionChanged()
        {            
            try
            {
                // Reload the data to context based on the selected category
                Category item = SelectedCategory;
                if (item != null && item.CategoryID > 0)
                {
                    _productListModel.GetCategorizedProducts((int)item.CategoryID);                    
                }

                // Remove the "Please Select"
                if (SelectedCategory != _comboDefault)
                {
                    CategoryItems.Remove(_comboDefault);
                }

                // Enable the Add button
                AddProductCommand.RaiseCanExecuteChanged();

            }
            catch (Exception ex)
            {
                Messenger.Default.Send(ex, MessageToken.RaiseErrorMessage);
            }
        }

        private RelayCommand _addProductCommand;
        //
        public RelayCommand AddProductCommand
        {
            get
            {
                if (_addProductCommand == null)
                {
                    _addProductCommand = new RelayCommand(
                        OnAddProductCommand,
                        () => SelectedCategory != null && SelectedCategory.CategoryID > 0);
                }
                return _addProductCommand;
            }
        }
        //
        private void OnAddProductCommand()
        {
            Messenger.Default.Send("", MessageToken.LoadAddProductViewMessage);
            Messenger.Default.Send(SelectedCategory, MessageToken.DataToAddProductVmMessage);
        }
        //
        private void OnDataToProductListVmMessage(Product addedProduct)
        {
            try
            {
                if (!_productListModel.IsBusy && addedProduct != null)
                {
                    // Add to Context in the model
                    _productListModel.AddNewProduct(addedProduct);

                    // Add to ObCollection for refreshing display
                    ProductItems.Add(addedProduct);
                }
            }
            catch (Exception ex)
            {
                Messenger.Default.Send(ex, MessageToken.RaiseErrorMessage);
            }
        }

        private RelayCommand _saveChangesCommand;
        //
        public RelayCommand SaveChangesCommand
        {
            get
            {
                if (_saveChangesCommand == null)
                {
                    _saveChangesCommand = new RelayCommand(
                        OnSaveChangesCommand,
                        () => CurrentProduct != null);
                }
                return _saveChangesCommand;
            }
        }
        //
        private void OnSaveChangesCommand()
        {
            try
            {
                if (!_productListModel.IsBusy && _productListModel.HasChanges)
                {
                    _productListModel.SaveChanges(OperationTypes.Update);
                    SaveChangesCommand.CanExecute(false);
                }                
            }
            catch (Exception ex)
            {
                Messenger.Default.Send(ex, MessageToken.RaiseErrorMessage);
            }
        }
        
        private RelayCommand _deleteProductCommand;
        //
        public RelayCommand DeleteProductCommand
        {
            get
            {
                if (_deleteProductCommand == null)
                {
                    _deleteProductCommand = new RelayCommand(
                        OnDeleteProductCommand,
                        () => CurrentProduct != null);
                }
                return _deleteProductCommand;
            }
        }
        //
        private void OnDeleteProductCommand()
        {
            try
            {
                if (!_productListModel.IsBusy && CurrentProduct != null)
                {
                    // Send dialog message with callback from user response
                    MessageBoxResult theResult = MessageBoxResult.Cancel;
                    var dialogMessage = new DialogMessage(this,
                            StaticText.MessageBoxDeleteConfirmation,
                            rs => theResult = rs)
                    {
                        Button = MessageBoxButton.OKCancel,
                        Caption = StaticText.MessageBoxConfirmationCaption
                    };
                    
                    Messenger.Default.Send(dialogMessage, MessageToken.UseDialogMessage);
                    
                    if (theResult == MessageBoxResult.OK)
                    {
                        _productListModel.DeleteProduct(CurrentProduct);
                        
                        // Remove the item in the display
                        ProductItems.Remove(CurrentProduct);
                    }
                }
            }
            catch (Exception ex)
            {
                Messenger.Default.Send(ex, MessageToken.RaiseErrorMessage);
            }
        }

        private RelayCommand _dataGridSelectionChanged;
        //
        public RelayCommand DataGridSelectionChanged
        {
            get
            {
                if (_dataGridSelectionChanged == null)
                {
                    _dataGridSelectionChanged = new RelayCommand(
                        OnDataGridSelectionChanged,
                        () => true);
                }
                return _dataGridSelectionChanged;
            }
        }
        //
        private void OnDataGridSelectionChanged()
        {
            try
            {
                // Enable buttons                
                SaveChangesCommand.RaiseCanExecuteChanged();
                DeleteProductCommand.RaiseCanExecuteChanged();
            }
            catch (Exception ex)
            {
                Messenger.Default.Send(ex, MessageToken.RaiseErrorMessage);
            }
        }
          
        private void ProductListModel_GetCategryComplete(object sender, QueryResultsArgs<Category> e)
        {
            if (!e.HasError)
            {
                // Set the returned data from async loading to data object
                CategoryItems = e.Results;                
                
                if (SelectedCategory == null)
                {
                    // Add the combo default item "Please Select"
                    CategoryItems.Insert(0, _comboDefault);

                    // Set selected category if not from state cache
                    SelectedCategory = CategoryItems[0];
                }
            }
            else
            {
                // Send error message
                Messenger.Default.Send(e.Error, MessageToken.RaiseErrorMessage);
            }
        }
        
        private void ProductListModel_GetCategorizedProductComplete(object sender, QueryResultsArgs<Product> e)
        {
            if (!e.HasError)
            {                
                ProductItems = e.Results;
            }
            else
            {
                // Send error message
                Messenger.Default.Send(e.Error, MessageToken.RaiseErrorMessage);
            }
        }

        private void ProductListModel_SaveChangesComplete(object sender, SubmitOperationArgs e)
        {
            string msgBody = string.Empty;
            if (!e.HasError)
            {                                
                // Send different messages for particular type of operations
                switch (_productListModel.CurrentOperation)
                {                    
                    case OperationTypes.AddNew:
                        msgBody = StaticText.MessageBoxAddNewDone;
                        break;
                    case OperationTypes.Update:
                        msgBody = StaticText.MessageBoxSaveChangesDone;
                        break;
                    case OperationTypes.Delete:
                        msgBody = StaticText.MessageBoxDeleteDone;
                        break;
                 default:
                        msgBody = StaticText.MessageBoxSaveChangesDone;
                        break;
                }

                var dialogMessage = new DialogMessage(this, msgBody, null)
                {
                    Button = MessageBoxButton.OK,
                    Caption = StaticText.MessageBoxStatusCaption
                };

                Messenger.Default.Send(dialogMessage, MessageToken.UseDialogMessage);
            }
            else
            {
                // Send error message
                Messenger.Default.Send(e.Error, MessageToken.RaiseErrorMessage);
            }
        } 
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
Shenwei is a software developer and architect, and has been working on business applications using Microsoft and Oracle technologies since 1996. He obtained Microsoft Certified Systems Engineer (MCSE) in 1998 and Microsoft Certified Solution Developer (MCSD) in 1999. He has experience in ASP.NET, C#, Visual Basic, Windows and Web Services, Silverlight, WPF, JavaScript/AJAX, HTML, SQL Server, and Oracle.

Comments and Discussions