Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version
Go to top

A Sample Silverlight 4 Application Using MEF, MVVM, and WCF RIA Services - Part 1

, 7 Jul 2011
Part 1 of a series describing the creation of a Silverlight business application using MEF, MVVM Light, and WCF RIA Services.
IssueVisionforSilverlightSetup20110630.zip
IssueVision for Silverlight Setup
IssueVisionSetup.msi
setup.exe
IssueVision_for_Silverlight_setup.zip
IssueVisionSetup.msi
setup.exe
IssueVision_Silverlight20110630.zip
IssueVision.Silverlight
Assemblies
GalaSoft.MvvmLight.Extras.SL4.dll
GalaSoft.MvvmLight.SL4.dll
MenuControls.dll
System.Windows.Controls.DataVisualization.Toolkit.dll
System.Windows.Controls.Toolkit.dll
System.Windows.Controls.Toolkit.Internals.dll
System.Windows.Interactivity.dll
Database
IssueVision.Client
IssueVision.Client.csproj.user
Assets
Signin.png
Controls
Properties
Views
IssueVision.Common
IssueVision.Common.csproj.user
Controls
Helpers
Models
Properties
Resources
Themes
IssueVision.Data
IssueVision.Data.csproj.user
Properties
Web
Resources
IssueVision.Data.Web
IssueVision.edmx
Helpers
MetadataClasses
Properties
Resources
Services
IssueVision.Model
IssueVision.Model.csproj.user
Properties
IssueVision.Setup
IssueVisionSetup.vdproj
IssueVision.ViewModel
IssueVision.ViewModel.csproj.user
Properties
IssueVision.Web
IssueVision.Web.csproj.user
Properties
IssueVision_Silverlight_20110316.zip
GalaSoft.MvvmLight.Extras.SL4.dll
GalaSoft.MvvmLight.SL4.dll
MenuControls.dll
System.Windows.Controls.DataVisualization.Toolkit.dll
System.Windows.Controls.Toolkit.dll
System.Windows.Controls.Toolkit.Internals.dll
System.Windows.Interactivity.dll
IssueVision.Client.csproj.user
Signin.png
DataSources
IssueVision.Data.Web.IssueVisionContext.datasource
IssueVision.Data.Web.PasswordResetContext.datasource
IssueVision.Common.csproj.user
IssueVision.Data.csproj.user
IssueVision.edmx
DataTypes
IssueVision.Model.csproj.user
IssueVisionSetup.vdproj
IssueVision.ViewModel.csproj.user
IssueVision.Web.csproj.user
IssueVision_Silverlight_20110606.zip
GalaSoft.MvvmLight.Extras.SL4.dll
GalaSoft.MvvmLight.SL4.dll
MenuControls.dll
System.Windows.Controls.DataVisualization.Toolkit.dll
System.Windows.Controls.Toolkit.dll
System.Windows.Controls.Toolkit.Internals.dll
System.Windows.Interactivity.dll
IssueVision.Client.csproj.user
Signin.png
IssueVision.Common.csproj.user
IssueVision.Data.csproj.user
IssueVision.edmx
IssueVision.Model.csproj.user
IssueVisionSetup.vdproj
IssueVision.ViewModel.csproj.user
IssueVision.Web.csproj.user
IssueVision_Silverlight_Setup.zip
IssueVisionSetup.msi
setup.exe
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.Windows;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using IssueVision.Data.Web;
using IssueVision.Common;

namespace IssueVision.ViewModel
{
    [Export(ViewModelTypes.IssueEditorViewModel, typeof(ViewModelBase))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class IssueEditorViewModel : ViewModelBase
    {
        #region "Private Data Members"
        private IIssueVisionModel _issueVisionModel;
        private Issue _currentIssueCache;
        #endregion "Private Data Members"

        #region "Constructor"
        [ImportingConstructor]
        public IssueEditorViewModel(IIssueVisionModel issueVisionModel)
        {
            _issueVisionModel = issueVisionModel;

            // set up event handling
            _issueVisionModel.GetIssueTypesComplete += _issueVisionModel_GetIssueTypesComplete;
            _issueVisionModel.GetPlatformsComplete += _issueVisionModel_GetPlatformsComplete;
            _issueVisionModel.GetResolutionsComplete += _issueVisionModel_GetResolutionsComplete;
            _issueVisionModel.GetStatusesComplete += _issueVisionModel_GetStatusesComplete;
            _issueVisionModel.GetSubStatusesComplete += _issueVisionModel_GetSubStatusesComplete;
            _issueVisionModel.GetUsersComplete += _issueVisionModel_GetUsersComplete;

            // set _currentIssueCache to null
            _currentIssueCache = null;

            // load issue type entries
            IssueTypeEntries = null;
            _issueVisionModel.GetIssueTypesAsync();
            // load platform entries
            PlatformEntries = null;
            _issueVisionModel.GetPlatformsAsync();
            //load resolution entries
            ResolutionEntriesWithNull = null;
            _issueVisionModel.GetResolutionsAsync();
            // load status entries
            StatusEntries = null;
            _issueVisionModel.GetStatusesAsync();
            // load substatus entries
            SubstatusEntriesWithNull = null;
            _issueVisionModel.GetSubStatusesAsync();
            // load user entries
            UserEntries = null;
            UserEntriesWithNull = null;
            _issueVisionModel.GetUsersAsync();

            // register for EditIssueMessage
            AppMessages.EditIssueMessage.Register(this, OnEditIssueMessage);
        }
        #endregion "Constructor"

        #region "ICleanup interface implementation"
        public override void Cleanup()
        {
            if (_issueVisionModel != null)
            {
                // unregister all events
                _issueVisionModel.GetIssueTypesComplete -= _issueVisionModel_GetIssueTypesComplete;
                _issueVisionModel.GetPlatformsComplete -= _issueVisionModel_GetPlatformsComplete;
                _issueVisionModel.GetResolutionsComplete -= _issueVisionModel_GetResolutionsComplete;
                _issueVisionModel.GetStatusesComplete -= _issueVisionModel_GetStatusesComplete;
                _issueVisionModel.GetSubStatusesComplete -= _issueVisionModel_GetSubStatusesComplete;
                _issueVisionModel.GetUsersComplete -= _issueVisionModel_GetUsersComplete;
                _issueVisionModel = null;
            }
            // set properties back to null
            CurrentIssue = null;
            IssueTypeEntries = null;
            PlatformEntries = null;
            ResolutionEntriesWithNull = null;
            StatusEntries = null;
            SubstatusEntriesWithNull = null;
            UserEntries = null;
            UserEntriesWithNull = null;
            // unregister any messages for this ViewModel
            base.Cleanup();
        }
        #endregion "ICleanup interface implementation"

        #region "Public Properties"

        private Issue _currentIssue;

        public Issue CurrentIssue
        {
            get { return _currentIssue; }
            private set
            {
                if (!ReferenceEquals(_currentIssue, value))
                {
                    _currentIssue = value;
                    RaisePropertyChanged("CurrentIssue");
                }
            }
        }

        private IEnumerable<byte> _priorityEntries;

        public IEnumerable<byte> PriorityEntries
        {
            get
            {
                if (_priorityEntries == null)
                {
                    var priorityList = new List<byte>();
                    for (var i = IssueVisionServiceConstant.HighestPriority; i <= IssueVisionServiceConstant.LowestPriority; i++)
                    {
                        priorityList.Add(i);
                    }
                    _priorityEntries = priorityList.AsEnumerable();
                }
                return _priorityEntries;
            }
        }

        private IEnumerable<byte> _severityEntries;

        public IEnumerable<byte> SeverityEntries
        {
            get
            {
                if (_severityEntries == null)
                {
                    var severityList = new List<byte>();
                    for (var i = IssueVisionServiceConstant.HighestSeverity; i <= IssueVisionServiceConstant.LowestSeverity; i++)
                    {
                        severityList.Add(i);
                    }
                    _severityEntries = severityList.AsEnumerable();
                }
                return _severityEntries;
            }
        }

        private IEnumerable<IssueType> _issueTypeEntries;

        public IEnumerable<IssueType> IssueTypeEntries
        {
            get { return _issueTypeEntries; }
            private set
            {
                if (!ReferenceEquals(_issueTypeEntries, value))
                {
                    _issueTypeEntries = value;
                    RaisePropertyChanged("IssueTypeEntries");
                }
            }
        }

        private IEnumerable<Platform> _platformEntries;

        public IEnumerable<Platform> PlatformEntries
        {
            get { return _platformEntries; }
            private set
            {
                if (!ReferenceEquals(_platformEntries, value))
                {
                    _platformEntries = value;
                    RaisePropertyChanged("PlatformEntries");
                }
            }
        }

        private IEnumerable<Resolution> _resolutionEntriesWithNull;

        public IEnumerable<Resolution> ResolutionEntriesWithNull
        {
            get { return _resolutionEntriesWithNull; }
            private set
            {
                if (!ReferenceEquals(_resolutionEntriesWithNull, value))
                {
                    _resolutionEntriesWithNull = value;
                    RaisePropertyChanged("ResolutionEntriesWithNull");
                }
            }
        }

        private IEnumerable<Status> _statusEntries;

        public IEnumerable<Status> StatusEntries
        {
            get { return _statusEntries; }
            private set
            {
                if (!ReferenceEquals(_statusEntries, value))
                {
                    _statusEntries = value;
                    RaisePropertyChanged("StatusEntries");
                }
            }
        }

        private IEnumerable<SubStatus> _substatusEntriesWithNull;

        public IEnumerable<SubStatus> SubstatusEntriesWithNull
        {
            get { return _substatusEntriesWithNull; }
            private set
            {
                if (!ReferenceEquals(_substatusEntriesWithNull, value))
                {
                    _substatusEntriesWithNull = value;
                    RaisePropertyChanged("SubstatusEntriesWithNull");
                }
            }
        }

        private IEnumerable<User> _userEntries;

        public IEnumerable<User> UserEntries
        {
            get { return _userEntries; }
            private set
            {
                if (!ReferenceEquals(_userEntries, value))
                {
                    _userEntries = value;
                    RaisePropertyChanged("UserEntries");
                }
            }
        }

        private IEnumerable<User> _userEntriesWithNull;

        public IEnumerable<User> UserEntriesWithNull
        {
            get { return _userEntriesWithNull; }
            private set
            {
                if (!ReferenceEquals(_userEntriesWithNull, value))
                {
                    _userEntriesWithNull = value;
                    RaisePropertyChanged("UserEntriesWithNull");
                }
            }
        }

        #endregion "Public Properties"

        #region "Public Commands"

        private RelayCommand<DragEventArgs> _handleDropCommand;

        public RelayCommand<DragEventArgs> HandleDropCommand
        {
            get
            {
                if (_handleDropCommand == null)
                {
                    _handleDropCommand = new RelayCommand<DragEventArgs>(
                        OnHandleDropCommand,
                        e => CurrentIssue != null);
                }
                return _handleDropCommand;
            }
        }

        private void OnHandleDropCommand(DragEventArgs e)
        {
            try
            {
                // get a list of files as FileInfo objects
                var files = e.Data.GetData(DataFormats.FileDrop) as FileInfo[];

                if (files != null)
                {
                    // loop through the list and read each file
                    foreach (var file in files)
                    {
                        using (var fs = file.OpenRead())
                        using (var ms = new MemoryStream())
                        {
                            fs.CopyTo(ms);
                            // and then add each file into the Files entity collection
                            CurrentIssue.Files.Add(
                                new Data.Web.File
                                {
                                    FileID = Guid.NewGuid(),
                                    IssueID = CurrentIssue.IssueID,
                                    FileName = file.Name,
                                    Data = ms.GetBuffer()
                                });
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(ex);
            }
        }

        private RelayCommand _addFileCommand;

        public RelayCommand AddFileCommand
        {
            get
            {
                if (_addFileCommand == null)
                {
                    _addFileCommand = new RelayCommand(
                        OnAddFileCommand,
                        () => CurrentIssue != null);
                }
                return _addFileCommand;
            }
        }

        private void OnAddFileCommand()
        {
            try
            {
                if (!_issueVisionModel.IsBusy)
                {
                    FileInfo addedFile = null;
                    // ask user for a file to add
                    AppMessages.OpenFileMessage.Send(
                        new NotificationMessageAction<FileInfo>("Open File", g => addedFile = g));

                    if (addedFile != null)
                    {
                        using (var fs = addedFile.OpenRead())
                        using (var ms = new MemoryStream())
                        {
                            fs.CopyTo(ms);
                            // and then add the file into the Files entity collection
                            CurrentIssue.Files.Add(
                                new Data.Web.File
                                {
                                    FileID = Guid.NewGuid(),
                                    IssueID = CurrentIssue.IssueID,
                                    FileName = addedFile.Name,
                                    Data = ms.GetBuffer()
                                });
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(ex);
            }
        }

        private RelayCommand<Data.Web.File> _removeFileCommand;

        public RelayCommand<Data.Web.File> RemoveFileCommand
        {
            get
            {
                if (_removeFileCommand == null)
                {
                    _removeFileCommand = new RelayCommand<Data.Web.File>(
                        OnRemoveFileCommand,
                        g => g != null);
                }
                return _removeFileCommand;
            }
        }

        private void OnRemoveFileCommand(Data.Web.File g)
        {
            try
            {
                if (!_issueVisionModel.IsBusy)
                {
                    CurrentIssue.Files.Remove(g);
                    _issueVisionModel.RemoveFile(g);
                }
            }
            catch (Exception ex)
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(ex);
            }
        }

        private RelayCommand<Data.Web.File> _saveToDiskCommand;

        public RelayCommand<Data.Web.File> SaveToDiskCommand
        {
            get
            {
                if (_saveToDiskCommand == null)
                {
                    _saveToDiskCommand = new RelayCommand<Data.Web.File>(g =>
                    {
                        if (!_issueVisionModel.IsBusy)
                        {
                            AppMessages.SaveFileMessage.Send(g);
                        }
                    }, g => g != null);
                }
                return _saveToDiskCommand;
            }
        }

        private RelayCommand _addAttributeCommand;

        public RelayCommand AddAttributeCommand
        {
            get
            {
                if (_addAttributeCommand == null)
                {
                    _addAttributeCommand = new RelayCommand(
                        OnAddAttributeCommand,
                        () => CurrentIssue != null);
                }
                return _addAttributeCommand;
            }
        }

        private void OnAddAttributeCommand()
        {
            if (!_issueVisionModel.IsBusy)
            {
                CurrentIssue.Attributes.Add(
                    new Data.Web.Attribute
                    {
                        ID = Guid.NewGuid(),
                        IssueID = CurrentIssue.IssueID,
                        AttributeName = "Key",
                        Value = "Value"
                    });
            }
        }

        private RelayCommand<Data.Web.Attribute> _removeAttributeCommand;

        public RelayCommand<Data.Web.Attribute> RemoveAttributeCommand
        {
            get
            {
                if (_removeAttributeCommand == null)
                {
                    _removeAttributeCommand = new RelayCommand<Data.Web.Attribute>(g =>
                    {
                        if (!_issueVisionModel.IsBusy)
                        {
                            CurrentIssue.Attributes.Remove(g);
                            _issueVisionModel.RemoveAttribute(g);
                        }
                    }, g => g != null);
                }
                return _removeAttributeCommand;
            }
        }

        #endregion "Public Commands"

        #region "Private Methods"

        private void _issueVisionModel_GetIssueTypesComplete(object sender, EntityResultsArgs<IssueType> e)
        {
            if (!e.HasError)
            {
                IssueTypeEntries = e.Results.OrderBy(g => g.Name);
                // check whether IssueTypeEntries is populated after CurrentIssue
                AssignCurrentIssue(null);
            }
            else
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(e.Error);
            }
        }

        private void _issueVisionModel_GetPlatformsComplete(object sender, EntityResultsArgs<Platform> e)
        {
            if (!e.HasError)
            {
                PlatformEntries = e.Results.OrderBy(g => g.OS).ThenBy(g => g.OSVersion);
                // check whether PlatformEntries is populated after CurrentIssue
                AssignCurrentIssue(null);
            }
            else
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(e.Error);
            }
        }

        private void _issueVisionModel_GetResolutionsComplete(object sender, EntityResultsArgs<Resolution> e)
        {
            if (!e.HasError)
            {
                // create a new resolution list with the first item of null Name
                var resolutionList = e.Results.ToList();
                resolutionList.Add(new Resolution());
                ResolutionEntriesWithNull = resolutionList.OrderBy(g => g.Name).AsEnumerable();
                // check whether ResolutionEntriesWithNull is populated after CurrentIssue
                AssignCurrentIssue(null);
            }
            else
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(e.Error);
            }
        }

        private void _issueVisionModel_GetStatusesComplete(object sender, EntityResultsArgs<Status> e)
        {
            if (!e.HasError)
            {
                StatusEntries = e.Results.OrderBy(g => g.StatusID);
                // check whether StatusEntries is populated after CurrentIssue
                AssignCurrentIssue(null);
            }
            else
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(e.Error);
            }
        }

        private void _issueVisionModel_GetSubStatusesComplete(object sender, EntityResultsArgs<SubStatus> e)
        {
            if (!e.HasError)
            {
                // create a new substatus list with the first item of null Name
                var substatusList = e.Results.ToList();
                substatusList.Add(new SubStatus());
                SubstatusEntriesWithNull = substatusList.OrderBy(g => g.Name).AsEnumerable();
                // check whether SubstatusEntriesWithNull is populated after CurrentIssue
                AssignCurrentIssue(null);
            }
            else
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(e.Error);
            }
        }

        private void _issueVisionModel_GetUsersComplete(object sender, EntityResultsArgs<User> e)
        {
            if (!e.HasError)
            {
                UserEntries = e.Results.OrderBy(g => g.Name);
                // create a new user list with the first item of null user name
                var userList = e.Results.ToList();
                userList.Add(new User());
                UserEntriesWithNull = userList.OrderBy(g => g.Name).AsEnumerable();
                // check whether UserEntries/UserEntriesWithNull is populated after CurrentIssue
                AssignCurrentIssue(null);
            }
            else
            {
                // notify user if there is any error
                AppMessages.RaiseErrorMessage.Send(e.Error);
            }
        }

        private void OnEditIssueMessage(Issue editIssue)
        {
            if (editIssue == null) return;
            // check whether this issue is read-only or not
            AppMessages.ReadOnlyIssueMessage.Send(editIssue.IsIssueReadOnly());

            AssignCurrentIssue(editIssue);
        }

        /// <summary>
        /// Assign edit issue only after all ComboBox are ready
        /// </summary>
        /// <param name="editIssue"></param>
        private void AssignCurrentIssue(Issue editIssue)
        {
            if (editIssue != null)
            {
                // this call is coming from OnEditIssueMessage()
                if (IssueTypeEntries != null && PlatformEntries != null &&
                    ResolutionEntriesWithNull != null && StatusEntries != null &&
                    SubstatusEntriesWithNull != null && UserEntries != null &&
                    UserEntriesWithNull != null)
                {
                    // if all ComboBox are ready, we set CurrentIssue
                    CurrentIssue = editIssue;
                    _currentIssueCache = null;
                }
                else
                    _currentIssueCache = editIssue;
            }
            else
            {
                // this call is coming from one of the complete event handlers
                if (_currentIssueCache != null && IssueTypeEntries != null &&
                    PlatformEntries != null && ResolutionEntriesWithNull != null &&
                    StatusEntries != null && SubstatusEntriesWithNull != null &&
                    UserEntries != null && UserEntriesWithNull != null)
                {
                    // if all ComboBox are ready, we set CurrentIssue
                    CurrentIssue = _currentIssueCache;
                    _currentIssueCache = null;
                }
            }
        }

        #endregion "Private Methods"
    }
}

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)

Share

About the Author

Weidong Shen
Software Developer (Senior)
United States United States
Weidong has been an information system professional since 1990. He has a Master's degree in Computer Science, and is currently a MCSD .NET

| Advertise | Privacy | Mobile
Web01 | 2.8.140916.1 | Last Updated 7 Jul 2011
Article Copyright 2010 by Weidong Shen
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid