Click here to Skip to main content
15,881,938 members
Articles / Desktop Programming / WPF

GoalBook - A Hybrid Smart Client

Rate me:
Please Sign up or sign in to vote.
4.86/5 (24 votes)
25 Sep 2009CPOL10 min read 79K   834   69  
A WPF hybrid smart client that synchronises your goals with the Toodledo online To-do service.
// <copyright file="NotesViewPresenter.cs" company="GoalBook"> 
//    Copyright © 2009 Mark Brownsword. All rights reserved.
//    This source code and supporting files are licensed under The Code Project  
//    Open License (CPOL) as detailed at http://www.codeproject.com/info/cpol10.aspx. 
// </copyright>
namespace GoalBook.Notes.Views
{
    #region Using Statements
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Linq;
    using System.Windows;
    using System.Windows.Documents;
    using System.Windows.Input;
    using Csla;
    using GoalBook.Infrastructure;
    using GoalBook.Infrastructure.Constants;
    using GoalBook.Infrastructure.Converters;
    using GoalBook.Infrastructure.Enums;
    using GoalBook.Infrastructure.Events;
    using GoalBook.Infrastructure.Helpers;
    using GoalBook.Infrastructure.Interfaces;
    using GoalBook.Infrastructure.ObjectModel;
    using Infragistics.Windows.DataPresenter;
    using Microsoft.Practices.Composite.Events;
    using Microsoft.Practices.Composite.Presentation.Commands;
    using Microsoft.Practices.Composite.Presentation.Events;
    #endregion

    /// <summary>
    /// NotesView Presenter. Interaction logic for NotesView.
    /// </summary>
    public class NotesViewPresenter
    {
        #region Constants and Enums
        /// <summary>
        /// Declaration for navigationService.
        /// </summary>
        private readonly INavigationService navigationService;

        /// <summary>
        /// Declaration for dialogService.
        /// </summary>
        private readonly IDialogService dialogService;

        /// <summary>
        /// Declaration for loggerService.
        /// </summary>
        private readonly ILoggerService loggerService;

        /// <summary>
        /// Declaration for persistenceService.
        /// </summary>
        private readonly IPersistenceService persistenceService;

        /// <summary>
        /// Declaration for eventAggregator.
        /// </summary>
        private readonly IEventAggregator eventAggregator;

        /// <summary>
        /// Declaration for printService.
        /// </summary>
        private readonly IPrintService printService;

        /// <summary>
        /// Declaration for settingsService.
        /// </summary>
        private readonly ISettingsService settingsService;
        #endregion        

        #region Delegates and Events
        /// <summary>
        /// Declaration for newCommand.
        /// </summary>
        private DelegateCommand<CommandInfo> newCommand;

        /// <summary>
        /// Declaration for printCommand.
        /// </summary>
        private DelegateCommand<CommandInfo> printCommand;

        /// <summary>
        /// Declaration for undoCommand.
        /// </summary>
        private DelegateCommand<CommandInfo> undoCommand;

        /// <summary>
        /// Declaration for deleteCommand.
        /// </summary>
        private DelegateCommand<CommandInfo> deleteCommand;

        /// <summary>
        /// Declaration for searchCommand.
        /// </summary>
        private DelegateCommand<string> searchCommand;

        /// <summary>
        /// Declaration for clearCommand.
        /// </summary>
        private DelegateCommand<string> clearCommand;

        /// <summary>
        /// Declaration for XamlToFlowDocumentConverter.
        /// </summary>
        private XamlToFlowDocumentConverter xamlToFlowDocumentConverter;
        #endregion

        #region Instance and Shared Fields
        /// <summary>
        /// Declaration for syncInProgress.
        /// </summary>
        private bool syncInProgress = false;
        #endregion

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the NotesViewPresenter class.
        /// </summary>
        /// <param name="navigationService">Reference to navigationService</param>
        /// <param name="dialogService">Reference to dialogService</param>
        /// <param name="loggerService">Reference to loggerService</param>
        /// <param name="persistenceService">Reference to persistenceService</param>
        /// <param name="eventAggregator">Reference to eventAggregator</param>
        /// <param name="printService">Reference to printService</param> 
        /// <param name="settingsService">Reference to settingsService</param>
        public NotesViewPresenter(
            INavigationService navigationService, 
            IDialogService dialogService, 
            ILoggerService loggerService,
            IPersistenceService persistenceService, 
            IEventAggregator eventAggregator,
            IPrintService printService, 
            ISettingsService settingsService)
        {
            // Set references.
            this.dialogService = dialogService;
            this.navigationService = navigationService;
            this.loggerService = loggerService;
            this.persistenceService = persistenceService;
            this.eventAggregator = eventAggregator;
            this.printService = printService;
            this.settingsService = settingsService;

            // Initialise Model.
            this.Model = new NotesViewPresentationModel();
            this.Model.Notes = new FilteredBindingList<Note>(this.persistenceService.Notes);
            this.Model.FolderList = new SortedBindingList<KeyValueItem>(this.persistenceService.Folders.FolderKeyValueItemList);
            this.Model.Notes.ListChanged += this.Notes_ListChanged;

            // Initialise the XamlToFlowDocumentConverter.
            this.xamlToFlowDocumentConverter = new XamlToFlowDocumentConverter();

            // Subscribe to events.
            this.persistenceService.Folders.ListChanged += this.Folders_ListChanged;
            this.persistenceService.SaveOccured += this.PersistenceService_SaveOccured;
            this.eventAggregator.GetEvent<SyncBeginEvent>().Subscribe(this.SyncBegin_EventHandler, ThreadOption.UIThread, true);
            this.eventAggregator.GetEvent<SyncEndEvent>().Subscribe(this.SyncEnd_EventHandler, ThreadOption.UIThread, true);

            // Initialise ReferenceData.            
            ReferenceData.FolderList = this.persistenceService.FetchFolderList();

            // Initialise Composite Commands. Note that these commands are active aware 
            // and will only execute when this view is the currently active view.
            this.printCommand = new DelegateCommand<CommandInfo>(this.PrintExecute_EventHandler, this.CanPrintExecute_EventHandler);
            this.undoCommand = new DelegateCommand<CommandInfo>(this.UndoExecute_EventHandler, this.CanUndoExecute_EventHandler);
            this.deleteCommand = new DelegateCommand<CommandInfo>(this.DeleteExecute_EventHandler, this.CanDeleteExecute_EventHandler);
            this.searchCommand = new DelegateCommand<string>(this.SearchExecute_EventHandler, this.CanSearchExecute_EventHandler);
            this.clearCommand = new DelegateCommand<string>(this.ClearExecute_EventHandler, this.CanClearExecute_EventHandler);

            // Register the commands.
            this.navigationService.RegisterInfoCommand(GlobalCommandType.Print, this.printCommand);
            this.navigationService.RegisterInfoCommand(GlobalCommandType.Undo, this.undoCommand);
            this.navigationService.RegisterInfoCommand(GlobalCommandType.Delete, this.deleteCommand);
            this.navigationService.RegisterStringCommand(GlobalCommandType.Search, this.searchCommand);
            this.navigationService.RegisterStringCommand(GlobalCommandType.Clear, this.clearCommand);
            //// NB: Remember to set new commands IsActive property in the View_IsActiveChanged event.
        }
        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets Model.
        /// </summary>
        public NotesViewPresentationModel Model { get; set; }

        /// <summary>
        /// Gets or sets View.
        /// </summary>
        public NotesView View { get; set; }

        /// <summary>
        /// Gets or sets Reference to ActionView.
        /// </summary>
        public NotesActionView ActionView { get; set; }    

        /// <summary>
        /// Gets ViewMenuInfo. Called by Module 
        /// each time the this view is activated.
        /// </summary>
        public MenuInfo[] ViewMenuInfo
        {
            get { return this.GetMenuInfo(); }
        }        
        #endregion

        #region Public and internal Methods
        /// <summary>
        /// Initialise the View.
        /// </summary>
        public void InitViews()
        {
            this.View.DataContext = this.Model;
            this.View.NoteSelected += new EventHandler(this.View_ItemSelected);
            this.View.IsActiveChanged += new EventHandler(this.View_IsActiveChanged);
            this.View.Activated += new EventHandler(this.View_Activated);
            this.View.EditActionInitiated += new EditActionEventHandler(this.View_EditActionInitiated);

            this.ActionView.DataContext = this.Model;
            this.ActionView.FolderFilter = null;            
            this.ActionView.FilterChanged += new EventHandler(this.ActionView_FilterChanged);
                        
            this.Model.FolderList.ApplySort(KeyValueItem.OrderProperty.Name, ListSortDirection.Ascending);
            this.ApplyFilter();
        }

        /// <summary>
        /// Get New MenuInfo.
        /// </summary> 
        /// <returns>MenuInfo instance</returns>
        public MenuInfo GetNewMenuInfo()
        {
            MenuInfo menuInfo = new MenuInfo();

            this.newCommand = new DelegateCommand<CommandInfo>(this.NewExecute_EventHandler, this.CanNewExecute_EventHandler);
            menuInfo.MenuDelegateCommand = this.newCommand;
            menuInfo.MenuCommandInfo = new CommandInfo(
                Properties.Resources.NewNoteMenuText,
                0,
                ParentMenuType.New,
                new Uri(MenuConstants.MENU_NEW_NOTE_IMAGE_URI),
                new KeyGesture(Key.N, ModifierKeys.Control | ModifierKeys.Shift, Properties.Resources.ModifierKeyControlShiftN));

            return menuInfo;
        }
        #endregion

        #region Base Class Overrides
        #endregion

        #region Private and Protected Methods
        /// <summary>
        /// Apply Title Filter.
        /// </summary>
        /// <param name="parameter">filter parameter</param>
        private void ApplyTitleFilter(string parameter)
        {
            this.Model.Notes.FilterProvider = this.TitleFilter;
            this.Model.Notes.ApplyFilter(Note.IdProperty.Name, parameter);
        }

        /// <summary>
        /// Title Filter.
        /// </summary>
        /// <param name="item">item parameter</param>
        /// <param name="filter">filter parameter</param>
        /// <returns>True if filter item found</returns>
        private bool TitleFilter(object item, object filter)
        {
            bool result = false;

            Note target = this.persistenceService.Notes.Single(note => note.NoteID == new Guid(item.ToString()));
            
            if (target.Title.Contains(filter.ToString()) &&
                     this.FolderFilter(target.FolderID, this.ActionView.FolderFilter))
            {
                result = true;
            }

            return result;
        }

        /// <summary>
        /// Apply Filter.
        /// </summary>
        private void ApplyFilter()
        {
            if (this.ActionView.FolderFilter != null)
            {
                this.Model.Notes.FilterProvider = this.FolderFilter;
                this.Model.Notes.ApplyFilter(Note.FolderIdProperty.Name, this.ActionView.FolderFilter);
            }
        }

        /// <summary>
        /// Level Filter.
        /// </summary>
        /// <param name="item">item parameter</param>
        /// <param name="filter">filter parameter</param>
        /// <returns>True if filter item found</returns>
        private bool FolderFilter(object item, object filter)
        {            
            string[] filterSplit = filter.ToString().Split(',');

            for (int i = 0; i < filterSplit.Length; i++)
            {
                if (filterSplit[i] == item.ToString())
                {
                    return true;
                }
            }

            return false;
        }
                
        /// <summary>
        /// GetMenuInfo. Returns all menuinfo instances for the module.
        /// </summary> 
        /// <returns>MenuInfo instances</returns>
        private MenuInfo[] GetMenuInfo()
        {
            List<MenuInfo> list = new List<MenuInfo>();
            ////list.Add(this.GetNewMenuInfo());

            return list.ToArray();
        }
        
        /// <summary>
        /// Initialise the DialogOptions.
        /// </summary>
        /// <param name="title">title for the dialog</param>
        /// <returns>DialogOptions instance</returns>
        private DialogOptions InitialiseDialogOptions(string title)
        {
            // Initialise DialogOptions.
            DialogOptions options = new DialogOptions();
            options.AllowResize = false;
            options.DialogSize = new Size(600, 400);
            options.DialogTitle = title;
            options.IconUri = new Uri(MenuConstants.MENU_NEW_NOTE_IMAGE_URI);
            options.Buttons = ButtonType.OKCancel;

            return options;
        }

        /// <summary>
        /// Reset the List. Sorts item as required.
        /// </summary>
        private void ResetList()
        {
            // Refresh all list items.
            for (int i = 0; i < this.Model.Notes.Count; i++)
            {
                this.persistenceService.Notes.ResetItem(i);
            }
        }

        /// <summary>
        /// Preview Note.
        /// </summary>
        private void PreviewSelectedNote()
        {
            if (this.View.xamDataGridNotes.Records.Count == 0)
            {
                this.View.previewDocumentScrollViewer.Document = null;
                return;
            }

            foreach (DataRecord record in this.View.SelectedNotes)
            {
                if (record.DataItem is Note)
                {
                    Note selectedNote = this.GetClonedNote((record.DataItem as Note).NoteID);
                    if (selectedNote == null)
                    {
                        this.View.previewDocumentScrollViewer.Document = null;
                        return;
                    }
                    else
                    {
                        // Convert note to FlowDocument.
                        XamlToFlowDocumentConverter converter = new XamlToFlowDocumentConverter();
                        FlowDocument flowDocument = converter.Convert(selectedNote.Text, null, null, null) as FlowDocument;
                        flowDocument.PagePadding = new Thickness(5);

                        // Add Click event handler to each hyperlink.
                        FlowDocumentHelper helper = new FlowDocumentHelper(flowDocument);
                        foreach (Hyperlink hyperlink in helper.GetHyperlinks())
                        {
                            hyperlink.Click += this.Hyperlink_Click;
                            hyperlink.ToolTip = hyperlink.NavigateUri;
                            hyperlink.Focusable = false;
                        }

                        // Display selected note in previewer.
                        this.View.previewDocumentScrollViewer.Document = flowDocument;
                    }

                    break;
                }
            }
        }

        /// <summary>
        /// Initialise EditAction.
        /// </summary>
        /// <param name="e">EditActionEventArgs parameter</param>        
        private void InitialiseEditAction(EditActionEventArgs e)
        {
            SelectedRecordCollection records = e.Records;
            if (records.Count > 0 && records[records.Count - 1] is DataRecord)
            {
                // Edit the last item in the collection. That is the one with the row selector applied.
                DataRecord record = records[records.Count - 1] as DataRecord;

                if (record.DataItem is Note)
                {                    
                    this.PerformEditAction(this.InitialiseDialogOptions(Properties.Resources.EditNote), (record.DataItem as Note).Clone());
                    this.PreviewSelectedNote(); // Reloads the edited note.
                }
            }
        }
        
        /// <summary>
        /// Perform Add Action.
        /// </summary>
        /// <param name="options">DialogOptions parameter</param>
        /// <param name="note">Note parameter</param>       
        private void PerformAddAction(DialogOptions options, Note note)
        {
            // Initialise Presenter, Model and View.             
            NotesDialogViewPresenter presenter = new NotesDialogViewPresenter(note, this.persistenceService, this.dialogService);

            // Initialise View.
            presenter.View = new NotesDialogView();
            presenter.InitView();

            // Display the dialog.
            bool? result = this.dialogService.ShowView(
                presenter.View, 
                options,
                presenter.Model.EditNote as IDataErrorInfo);

            if (result == true)
            {
                Mouse.SetCursor(Cursors.Wait);

                // Extract note from view.
                presenter.Model.EditNote.Text = this.xamlToFlowDocumentConverter.ConvertBack(presenter.View.noteEditor.Document, null, null, null).ToString();

                if (presenter.Model.EditNote.IsSavable)
                {
                    presenter.Model.EditNote.Added = Convert.ToDateTime(DateTime.Now.ToString(SynchronisationConstants.SYNC_DATE_FORMAT));

                    this.persistenceService.Notes.BeginEdit();

                    // Add the pending item to the list.                
                    this.persistenceService.Notes.Add(presenter.Model.EditNote);
                    this.persistenceService.Notes.EndNew(this.Model.Notes.IndexOf(presenter.Model.EditNote));

                    // Refresh sort order.
                    this.View.SetItemActive(presenter.Model.EditNote);
                    this.PreviewSelectedNote();

                    this.View.RefreshSortPosition(true);
                }
            }
        }

        /// <summary>
        /// Perform EditAction.
        /// </summary>
        /// <param name="options">DialogOptions parameter</param>
        /// <param name="note">Note parameter</param>   
        private void PerformEditAction(DialogOptions options, Note note)
        {
            // Initialise Presenter, Model and View.              
            NotesDialogViewPresenter presenter = new NotesDialogViewPresenter(note, this.persistenceService, this.dialogService);

            // Initialise View.
            presenter.View = new NotesDialogView();
            presenter.InitView();

            // Display the dialog.
            bool? result = this.dialogService.ShowView(
                presenter.View, 
                options,
                presenter.Model.EditNote as IDataErrorInfo);

            if (result == true)
            {
                Mouse.SetCursor(Cursors.Wait);

                // Extract note from view.
                presenter.Model.EditNote.Text = this.xamlToFlowDocumentConverter.ConvertBack(presenter.View.noteEditor.Document, null, null, null).ToString();

                if (presenter.Model.EditNote.IsSavable)
                {
                    // Locate the note in the list.
                    for (int i = 0; i < this.Model.Notes.Count; i++)
                    {
                        if (this.Model.Notes[i].NoteID == note.NoteID)
                        {
                            this.persistenceService.Notes.BeginEdit();

                            // Apply the changes.
                            this.Model.Notes[i].MapFields(note);
                            
                            // Refresh the ActiveRecord - required if the grouping (FolderID) has changed.
                            this.View.RefreshSortPosition(true);

                            break;
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Perform DeleteAction.
        /// </summary>
        /// <param name="records">SelectedRecordCollection parameter</param>
        private void PerformDeleteAction(SelectedRecordCollection records)
        {                        
            Note note;
            foreach (DataRecord record in records)
            {
                note = record.DataItem as Note;

                // Initialise DialogOptions.
                DialogOptions options = new DialogOptions();
                options.AllowResize = false;                
                options.DialogTitle = Properties.Resources.DeleteNoteText;
                options.DialogMessage = string.Format(Properties.Resources.DeleteNoteMessageText, note.Title);
                options.IconUri = new Uri(MenuConstants.MESSAGE_ERROR_IMAGE_URI);
                options.Buttons = ButtonType.YesNo;

                if (this.dialogService.ShowMessageDialog(options) == true)
                {
                    this.persistenceService.Notes.BeginEdit();
                    this.persistenceService.Notes.Remove(note);
                }
            }
        }
        
        /// <summary>
        /// Raise NewCanExecuteChanged.
        /// </summary>
        private void RaiseNewCanExecuteChanged()
        {
            this.newCommand.RaiseCanExecuteChanged();
        }

        /// <summary>
        /// Raise PrintCanExecuteChanged.
        /// </summary>
        private void RaisePrintCanExecuteChanged()
        {
            this.printCommand.RaiseCanExecuteChanged();
        }

        /// <summary>
        /// Raise UndoCanExecuteChanged.
        /// </summary>
        private void RaiseUndoCanExecuteChanged()
        {
            this.undoCommand.RaiseCanExecuteChanged();
        }

        /// <summary>
        /// Raise DeleteCanExecuteChanged.
        /// </summary>
        private void RaiseDeleteCanExecuteChanged()
        {
            this.deleteCommand.RaiseCanExecuteChanged();
        }

        /// <summary>
        /// Raise SearchCanExecuteChanged.
        /// </summary>
        private void RaiseSearchCanExecuteChanged()
        {
            this.searchCommand.RaiseCanExecuteChanged();
        }

        /// <summary>
        /// Raise ClearCanExecuteChanged.
        /// </summary>
        private void RaiseClearCanExecuteChanged()
        {
            this.clearCommand.RaiseCanExecuteChanged();
        }

        /// <summary>
        /// Notify Command SyncInProgress. Ensure menuitems for editing
        /// goals are disabled during synchronisation.
        /// </summary>
        /// <param name="syncInProgress">Flag indicating if sync is running</param>
        private void NotifyCommandSyncInProgress(bool syncInProgress)
        {
            this.syncInProgress = syncInProgress;

            this.RaiseNewCanExecuteChanged();
            this.RaisePrintCanExecuteChanged();
            this.RaiseUndoCanExecuteChanged();
            this.RaiseDeleteCanExecuteChanged();
            this.RaiseSearchCanExecuteChanged();
            this.RaiseClearCanExecuteChanged();            
        }
        
        /// <summary>
        /// Select Active Record.
        /// </summary>
        private void SelectActiveRecord()
        {
            if (this.View.xamDataGridNotes.ActiveRecord != null)
            {
                this.View.xamDataGridNotes.Focus();
                this.View.xamDataGridNotes.ActiveRecord.IsSelected = true;
            }
        }

        /// <summary>
        /// Get Cloned Note.
        /// </summary>
        /// <param name="noteID">noteID parameter</param>
        /// <returns>Note matching the specified identifier or null</returns>
        private Note GetClonedNote(Guid noteID)
        {
            foreach (Note note in this.Model.Notes)
            {
                if (note.NoteID == noteID)
                {
                    return note.Clone();
                }
            }

            return null;
        }

        /// <summary>
        /// Show Status Count Message.
        /// </summary>
        private void ShowStatusCountMessage()
        {
            if (this.View.IsActive)
            {
                this.navigationService.ShowStatusMessage(string.Format(
                    Properties.Resources.StatusCountMessage,
                    this.Model.Notes.Count,
                    this.Model.Notes.Count == 1 ? string.Empty : Properties.Resources.StatusCountPluralCharacter,
                    this.persistenceService.Notes.Count));
            }
        }
        #endregion

        #region Event Handlers
        /// <summary>
        /// Handle ActionView_FilterChanged event.
        /// </summary>
        /// <param name="sender">sender parameter</param>
        /// <param name="e">EventArgs parameter</param>
        private void ActionView_FilterChanged(object sender, EventArgs e)
        {
            if (this.syncInProgress)
            {
                return;
            }
            
            this.ApplyFilter();            
        }

        /// <summary>
        /// Handle View_ItemSelected event.
        /// </summary>
        /// <param name="sender">sender parameter</param>
        /// <param name="e">EventArgs parameter</param>        
        private void View_ItemSelected(object sender, EventArgs e)
        {
            this.RaisePrintCanExecuteChanged();
            this.RaiseDeleteCanExecuteChanged();
             
            this.PreviewSelectedNote();
        }
        
        /// <summary>
        /// Handle View_Activated event.
        /// </summary>
        /// <param name="sender">sender parameter</param>
        /// <param name="e">EventArgs parameter</param>       
        private void View_Activated(object sender, EventArgs e)
        {
            this.SelectActiveRecord();            
            this.PreviewSelectedNote();
        }

        /// <summary>
        /// Handle View_EditActionInitiated event.
        /// </summary>
        /// <param name="e">EditActionEventArgs parameter</param>       
        private void View_EditActionInitiated(EditActionEventArgs e)
        {
            if (this.syncInProgress) 
            { 
                return; 
            }

            switch (e.EditAction)
            {
                case EditActionType.Cut:
                    break;
                case EditActionType.Copy:
                    break;
                case EditActionType.Paste:
                    break;
                case EditActionType.Delete:
                    break;
                case EditActionType.Edit:
                    this.InitialiseEditAction(e);
                    this.ApplyFilter();
                    break;
            }
        }

        /// <summary>
        /// Handle Notes_ListChanged event.
        /// </summary>
        /// <param name="sender">Source of caller</param>
        /// <param name="e">ListChangedEventArgs parameter</param>
        private void Notes_ListChanged(object sender, ListChangedEventArgs e)
        {
            this.RaisePrintCanExecuteChanged();
            this.RaiseUndoCanExecuteChanged();
            this.RaiseDeleteCanExecuteChanged();
            this.RaiseSearchCanExecuteChanged();
            this.RaiseClearCanExecuteChanged();

            this.PreviewSelectedNote();
            this.ShowStatusCountMessage();
        }

        /// <summary>
        /// Handle Folders_ListChanged event.
        /// </summary>
        /// <param name="sender">sender parameter</param>
        /// <param name="e">ListChangedEventArgs parameter</param>
        private void Folders_ListChanged(object sender, ListChangedEventArgs e)
        {            
            switch (e.ListChangedType)
            {
                case ListChangedType.ItemAdded:
                    if (this.ActionView.FolderFilter != null)
                    {
                        // Add new items to the FolderFilter, so they appear checked by default.
                        this.ActionView.FolderFilter += string.Concat(
                            this.ActionView.FolderFilter.Length > 0 ? "," : string.Empty,
                            this.persistenceService.Folders[e.NewIndex].FolderID.ToString());
                    }

                    break;  
                case ListChangedType.Reset:
                    this.ApplyFilter();                    
                    break;
            }
        }

        /// <summary>
        /// Handle PersistenceService_SaveOccured event.
        /// </summary>
        /// <param name="sender">Source of caller</param>
        /// <param name="e">EventArgs parameter</param>
        private void PersistenceService_SaveOccured(object sender, EventArgs e)
        {
            this.RaiseUndoCanExecuteChanged();
        }

        /// <summary>
        /// Handle SyncBegin_EventHandler event.
        /// </summary>
        /// <param name="payload">payload parameter</param>
        private void SyncBegin_EventHandler(string payload)
        {            
            this.NotifyCommandSyncInProgress(true);            
            this.ActionView.IsEnabled = this.ActionView.ListenForListChangedEvents = false;
        }

        /// <summary>
        /// Handle SyncEnd_EventHandler event.
        /// </summary>
        /// <param name="payload">payload parameter</param>
        private void SyncEnd_EventHandler(string payload)
        {            
            this.ResetList();            
                        
            if (this.View.IsActive)
            {
                this.View.Activate();
            }
            
            this.View.RefreshSortPosition(false);
            this.NotifyCommandSyncInProgress(false);

            this.ActionView.IsEnabled = this.ActionView.ListenForListChangedEvents = true;
           
            this.Model.FolderList.ApplySort(KeyValueItem.OrderProperty.Name, ListSortDirection.Ascending);
            
            this.ApplyFilter();            
        }

        /// <summary>
        /// Handle View_IsActiveChanged event.
        /// </summary>
        /// <param name="sender">Source of caller</param>
        /// <param name="e">EventArgs parameter</param>
        private void View_IsActiveChanged(object sender, EventArgs e)
        {            
            this.printCommand.IsActive =
            this.undoCommand.IsActive =
            this.deleteCommand.IsActive =
            this.searchCommand.IsActive =
            this.clearCommand.IsActive = this.View.IsActive;

            this.ShowStatusCountMessage();
        }

        /// <summary>
        /// Handle PrintExecute_EventHandler event.
        /// </summary>
        /// <param name="parameter">CommandInfo parameter</param>      
        private void PrintExecute_EventHandler(CommandInfo parameter)
        {
            foreach (DataRecord record in this.View.SelectedNotes)
            {
                if (record.DataItem is Note)
                {
                    XamlToFlowDocumentConverter converter = new XamlToFlowDocumentConverter();
                    FlowDocument flowDocument = converter.Convert((record.DataItem as Note).Text, null, null, null) as FlowDocument;                                        
                                        
                    this.printService.Print((record.DataItem as Note).Title, flowDocument);                    
                }
            }
        }

        /// <summary>
        /// Handle CanPrintExecute_EventHandler event.
        /// </summary>
        /// <param name="parameter">CommandInfo parameter</param>
        /// <returns>True if can print</returns>
        private bool CanPrintExecute_EventHandler(CommandInfo parameter)
        {
            return this.View.SelectedNotesCount > 0 && !this.syncInProgress;
        }

        /// <summary>
        /// Handle UndoExecute_EventHandler event.
        /// </summary>  
        /// <param name="parameter">CommandInfo parameter</param>
        private void UndoExecute_EventHandler(CommandInfo parameter)
        {
            // Roll the EditLevel back by one.
            this.persistenceService.Notes.CancelEdit();

            this.ResetList();
            this.SelectActiveRecord();
            this.PreviewSelectedNote();
        }

        /// <summary>
        /// Handle CanUndoExecute_EventHandler event.
        /// </summary> 
        /// <param name="parameter">CommandInfo parameter</param>
        /// <returns>True if command can execute</returns>
        private bool CanUndoExecute_EventHandler(CommandInfo parameter)
        {
            return this.persistenceService.Notes.EditLevel > 0 && !this.syncInProgress;
        }

        /// <summary>
        /// Handle DeleteExecute_EventHandler event.
        /// </summary>        
        /// <param name="parameter">CommandInfo parameter</param>
        private void DeleteExecute_EventHandler(CommandInfo parameter)
        {
            this.PerformDeleteAction(this.View.SelectedNotes);

            this.ResetList();
            this.SelectActiveRecord();
            this.PreviewSelectedNote();
        }
        
        /// <summary>
        /// Handle CanDeleteExecute_EventHandler event.
        /// </summary>        
        /// <param name="parameter">CommandInfo parameter</param>
        /// <returns>True if command can execute</returns>
        private bool CanDeleteExecute_EventHandler(CommandInfo parameter)
        {
            return this.View.SelectedNotesCount > 0 && !this.syncInProgress;
        }

        /// <summary>
        /// Handle SearchExecute_EventHandler event.
        /// </summary> 
        /// <param name="parameter">string parameter</param>        
        private void SearchExecute_EventHandler(string parameter)
        {
            this.ApplyTitleFilter(parameter);
        }

        /// <summary>
        /// Handle CanSearchExecute_EventHandler event.
        /// </summary>
        /// <param name="parameter">string parameter</param>
        /// <returns>True if command can execute</returns>
        private bool CanSearchExecute_EventHandler(string parameter)
        {
            return !this.syncInProgress;
        }

        /// <summary>
        /// Handle ClearExecute_EventHandler event.
        /// </summary>
        /// <param name="parameter">string parameter</param>
        private void ClearExecute_EventHandler(string parameter)
        {
            this.ApplyFilter();
        }

        /// <summary>
        /// Handle CanClearExecute_EventHandler event.
        /// </summary>
        /// <param name="parameter">string parameter</param>
        /// <returns>True if command can execute</returns>
        private bool CanClearExecute_EventHandler(string parameter)
        {
            return !this.syncInProgress;
        }

        /// <summary>
        /// Handle NewExecute_EventHandler event.
        /// </summary>
        /// <param name="parameter">CommandInfo parameter</param>
        private void NewExecute_EventHandler(CommandInfo parameter)
        {
            ToodledoToXamlConverter converter = new ToodledoToXamlConverter();
            
            Note note = new Note(Guid.NewGuid());                        
            note.Text = converter.Convert(string.Empty, null, null, null).ToString();

            this.PerformAddAction(this.InitialiseDialogOptions(Properties.Resources.NewNoteDialogText), note);
            this.ApplyFilter();            
        }

        /// <summary>
        /// Handle CanNewExecute_EventHandler event.
        /// </summary>        
        /// <param name="parameter">CommandInfo parameter</param>
        /// <returns>True if command can execute</returns>
        private bool CanNewExecute_EventHandler(CommandInfo parameter)
        {
            return !this.syncInProgress;
        }

        /// <summary>
        /// Handle Hyperlink_Click event.
        /// </summary>
        /// <param name="sender">sender parameter</param>
        /// <param name="e">RoutedEventArgs parameter</param>
        private void Hyperlink_Click(object sender, RoutedEventArgs e)
        {
            if (sender is Hyperlink)
            {
                Process p = new Process();
                p.StartInfo.FileName = (sender as Hyperlink).NavigateUri.ToString();
                p.StartInfo.UseShellExecute = true;
                p.StartInfo.RedirectStandardOutput = false;
                p.StartInfo.Arguments = string.Empty;

                p.Start();
            }
        }
        #endregion
    }
}

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
Software Developer (Senior)
Australia Australia
I've been working as a software developer since 2000 and hold a Bachelor of Business degree from The Open Polytechnic of New Zealand. Computers are for people and I aim to build applications for people that they would want to use.

Comments and Discussions