/// <summary>
        /// Opens the shell context menu instead of the normal context menu on right click.
        /// </summary>
        static void OnContextMenuOpening(object sender, ContextMenuEventArgs e)
        {
            Control control = sender as Control;

            // Attempt to open the explorer context menu for the application. If the file does not exist or
            // there is some other problem then a context menu (defined in the XAML) with just "Edit Entry"
            // and "Remove Entry" is opened instead.
            if (control != null && control.DataContext is ApplicationViewModel)
            {
                ApplicationViewModel application = (ApplicationViewModel)control.DataContext;

                if (File.Exists(application.FilePath))
                {
                    ContextMenuWrapper cmw = new ContextMenuWrapper();
                    cmw.OnQueryMenuItems += (QueryMenuItemsEventHandler)delegate(object s, QueryMenuItemsEventArgs args)
                    {
                        args.ExtraMenuItems = new string[] { "Edit Dock Entry", "Remove Dock Entry", "---" };

                        args.GrayedItems = new string[] { "delete", "rename", "cut", "copy" };
                        args.HiddenItems = new string[] { "link" };
                        args.DefaultItem = 1;
                    };
                    cmw.OnAfterPopup += (AfterPopupEventHandler) delegate(object s, AfterPopupEventArgs args)
                    {
                        Messenger.Default.Send<ShellContextMenuMessage>(ShellContextMenuMessage.Closed());
                    };

                    Messenger.Default.Send<ShellContextMenuMessage>(ShellContextMenuMessage.Opened());

                    try
                    {
                        FileSystemInfoEx[] files = new[] { FileInfoEx.FromString(application.FilePath) };
                        int[] position = Win32Mouse.GetMousePosition();
                        string command = cmw.Popup(files, new System.Drawing.Point(position[0], position[1]));

                        // Handle the click on the 'ExtraMenuItems'.
                        switch (command)
                        {
                            case "Edit Dock Entry":
                                Messenger.Default.Send<ApplicationMessage>(ApplicationMessage.Edit(application));
                                break;
                            case "Remove Dock Entry":
                                Messenger.Default.Send<ApplicationMessage>(ApplicationMessage.Remove(application));
                                break;
                        }
                        e.Handled = true; // Don't open the normal context menu.
                    }
                    catch (Exception ex)
                    {
                        Debug.Print("Problem displaying shell context menu: {0}", ex);
                    }
                }
            }
        }
        protected void SetupCommands(Func<ExModel[]> getSelectionFunc,
            Func<DirectoryModel> getCurrentFunc, Func<System.Drawing.Point> getMousePositionFunc)
        {
            #region OpenCommand and ContextMenuCommand
            OpenCommand = new SimpleRoutedCommand(ApplicationCommands.Open)
            {
                CanExecuteDelegate = x => { return getCurrentFunc() != null; },
                ExecuteDelegate = x => { Process.Start(getCurrentFunc().EmbeddedDirectoryEntry.FullName); }
            };

            ContextMenuCommand = new SimpleRoutedCommand(ApplicationCommands.ContextMenu)
            {
                CanExecuteDelegate = x =>
                {
                    return getSelectionFunc() != null && getSelectionFunc().Length > 0;
                },
                ExecuteDelegate = x =>
                {
                    ContextMenuWrapper _cmw = new ContextMenuWrapper();

                    _cmw.OnBeforeInvokeCommand += (InvokeCommandEventHandler)delegate(object sender, InvokeCommandEventArgs args)
                    {
                        if (args.Command == "open")
                            args.ContinueInvoke = false;
                        if (args.Command == "openas" && args.SelectedItems != null
                            && args.SelectedItems.Length == 1)
                            args.ContinueInvoke = false;
                    };
                    var selectedItems = (from model in getSelectionFunc() select model.EmbeddedEntry).ToArray();

                    System.Drawing.Point pt = getMousePositionFunc();
                    string command = _cmw.Popup(selectedItems, pt);
                    switch (command)
                    {
                        case "open": OpenCommand.Execute(null); break;
                        case "openas": OpenCommand.Execute(null); break;
                        case "rename": RenameCommand.Execute(null); break;
                        case "refresh": RefreshCommand.Execute(null); break;
                    }
                }
            };
            #endregion

            #region Delete, Copy and Paste
            DeleteCommand = new SimpleRoutedCommand(ApplicationCommands.Delete)
            {
                CanExecuteDelegate = x =>
                {
                    if (getSelectionFunc() != null && getSelectionFunc().Length > 0) ;
                    {
                        var selectedItems = (from model in getSelectionFunc() select model.EmbeddedEntry).ToArray();
                        foreach (FileSystemInfoEx item in selectedItems)
                        {
                            if ((item.Attributes & FileAttributes.ReadOnly) != 0)
                                return false;
                        }
                        return true;
                    }
                    //return false;
                },
                ExecuteDelegate = x =>
                {
                    var selectedItems = (from model in getSelectionFunc() select model.EmbeddedEntry).ToArray();
                    int itemCount = selectedItems.Length;
                    if (System.Windows.Forms.MessageBox.Show(String.Format("Are you sure want to permanently remove these {0} item{1}?",
                        itemCount, itemCount > 1 ? "s" : ""), "Delete", System.Windows.Forms.MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
                        foreach (FileSystemInfoEx item in selectedItems)
                            item.Delete();
                }
            };

            CopyCommand = new SimpleRoutedCommand(ApplicationCommands.Copy)
            {
                CanExecuteDelegate = x =>
                {
                    return getSelectionFunc() != null && getSelectionFunc().Length > 0;
                },
                ExecuteDelegate = x =>
                {
                    var selectedItems = (from model in getSelectionFunc() select model.EmbeddedEntry).ToArray();


                    StringCollection fileList = new StringCollection();

                    foreach (FileSystemInfoEx item in selectedItems)
                        fileList.Add(item.FullName);

                    Clipboard.Clear();
                    Clipboard.SetFileDropList(fileList);
                }
            };


            PasteCommand = new SimpleRoutedCommand(ApplicationCommands.Paste)
            {
                CanExecuteDelegate = x =>
                {
                    return
                        getCurrentFunc() != null &&
                        ((getCurrentFunc().EmbeddedDirectoryEntry.Attributes & FileAttributes.ReadOnly) != 0) &&
                        Clipboard.ContainsFileDropList();
                },
                ExecuteDelegate = x =>
                {
                    DirectoryInfoEx parentDir = getCurrentFunc().EmbeddedDirectoryEntry;
                    List<FileSystemInfoEx> entryList = new List<FileSystemInfoEx>();
                    foreach (string path in Clipboard.GetFileDropList())
                        IOTools.Copy(path, PathEx.Combine(parentDir.FullName, PathEx.GetFileName(path)));                        
                }
            };
            #endregion

            #region PropertiesCommand
            PropertiesCommand = new SimpleRoutedCommand(ApplicationCommands.Properties)
            {
                CanExecuteDelegate = x =>
                {
                    return getSelectionFunc() != null && getSelectionFunc().Length > 0;
                },
                ExecuteDelegate = x =>
                {
                    System.Windows.Point position = Mouse.GetPosition(null);
                    var selectedItems = (from model in getSelectionFunc() select model.EmbeddedEntry).ToArray();

                    ContextMenuHelper.InvokeCommand(getSelectionFunc()[0].EmbeddedEntry.Parent,
                        selectedItems, "properties", new System.Drawing.Point((int)position.X, (int)position.Y));
                }
            };
            #endregion
        }