/////////////////////////////////////////////////////////////////////////////////////////////////////
        // PUBLIC PROCEDURES
        /////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Returns the <c>ContextMenu</c> for the specified collection of view-models.
        /// </summary>
        /// <param name="ownerControl">The owner control.</param>
        /// <param name="viewModels">The view-models to examine.</param>
        /// <returns>The <c>ContextMenu</c> for the specified collection of view-models.</returns>
        public override ContextMenu GetItemContextMenu(TreeListBox ownerControl, IList <ShellObjectViewModel> viewModels)
        {
            var menu = base.GetItemContextMenu(ownerControl, viewModels);

            if (menu != null)
            {
                return(menu);
            }

            if (viewModels.Count == 1)
            {
                var shellObject = viewModels[0].Model as CustomShellObject;
                if (shellObject != null)
                {
                    menu = new ContextMenu();
                    menu.Items.Add(new MenuItem()
                    {
                        Header = "Custom Menu Item"
                    });
                    return(menu);
                }
            }

            return(null);
        }
示例#2
0
        public void TestResetItemsSource()
        {
            AvalonTestRunner.RunInSTA(delegate
            {
                //populate sample data
                List <string> businessObjects = new List <string>(4);
                businessObjects.Add("A");
                businessObjects.Add("AA");
                businessObjects.Add("AAA");
                businessObjects.Add("AAAA");
                businessObjects.Add("AAAA");

                TreeListBox treeListBox = new TreeListBox();
                treeListBox.ExposedGenerateItemsSource(businessObjects);

                //check that there are 4 items in the items source and that they are of type TreeLiistBoxInfo
                Assert.AreEqual(5, treeListBox.Items.Count,
                                "Invalid number of items added");
                for (int i = 0; i < treeListBox.Items.Count; i++)
                {
                    Assert.AreEqual(typeof(TreeListBoxInfo),
                                    treeListBox.Items[i].GetType(),
                                    "Invalid type added to tree list box");
                }
            });
        }
示例#3
0
        void IComponentConnector.Connect(int connectionId, object target)
        {
            switch (connectionId)
            {
            case 1:
                this.syncPicturesText = (CheckBox)target;
                return;

            case 2:
                this.syncAllPictures = (CheckBox)target;
                return;

            case 3:
                this.syncIncludeVideo = (CheckBox)target;
                return;

            case 4:
                this.pictureAlbumsTreeView = (TreeListBox)target;
                return;

            case 5:
                this.cancelButton = (Button)target;
                return;

            case 6:
                this.syncButton = (Button)target;
                return;
            }
            this._contentLoaded = true;
        }
        /// <summary>
        /// Sets whether the specified item is selected.
        /// </summary>
        /// <param name="ownerControl">The owner control.</param>
        /// <param name="item">The item to update.</param>
        /// <param name="value">The new value.</param>
        public override void SetIsSelected(TreeListBox ownerControl, object item, bool value)
        {
            var model = item as TreeNodeModel;

            if (model != null)
            {
                model.IsSelected = value;
            }
        }
示例#5
0
        /// <summary>
        /// Returns a string containing the full paths of the specified items.
        /// </summary>
        /// <param name="toolboxControl">The <see cref="TreeListBox"/> control.</param>
        /// <param name="items">The items to examine.</param>
        /// <returns>A string containing the full paths of the specified items.</returns>
        private static string JoinItemFullPaths(TreeListBox toolboxControl, IEnumerable <object> items)
        {
            var fullPaths = new StringBuilder();

            foreach (var item in items)
            {
                fullPaths.Append(toolboxControl.GetFullPath(item)).Append('\n');
            }
            return(fullPaths.ToString().TrimEnd());
        }
示例#6
0
        public TreeListsBinding(ITreeSource treeSource, TreeListBox directoryTreeListBox, TreeListBox directoryContentListBox)
        {
            Verify.Argument.IsNotNull(treeSource, nameof(treeSource));
            Verify.Argument.IsNotNull(directoryTreeListBox, nameof(directoryTreeListBox));
            Verify.Argument.IsNotNull(directoryContentListBox, nameof(directoryContentListBox));

            TreeSource              = treeSource;
            DirectoryTreeListBox    = directoryTreeListBox;
            DirectoryContentListBox = directoryContentListBox;

            Progress = directoryTreeListBox.ProgressMonitor;
        }
示例#7
0
        public TreeListsBinding(ITreeSource treeSource, TreeListBox directoryTreeListBox, TreeListBox directoryContentListBox)
        {
            Verify.Argument.IsNotNull(treeSource, "treeSource");
            Verify.Argument.IsNotNull(directoryTreeListBox, "directoryTreeListBox");
            Verify.Argument.IsNotNull(directoryContentListBox, "directoryContentListBox");

            _treeSource              = treeSource;
            _directoryTreeListBox    = directoryTreeListBox;
            _directoryContentListBox = directoryContentListBox;

            Progress = directoryTreeListBox.ProgressMonitor;
        }
示例#8
0
        void IComponentConnector.Connect(int connectionId, object target)
        {
            switch (connectionId)
            {
            case 1:
                this.syncMusicCheckBox = (CheckBox)target;
                return;

            case 2:
                this.syncAllMusicCheckBox = (CheckBox)target;
                return;

            case 3:
                this.playlistsLabel = (Label)target;
                return;

            case 4:
                this.playlistsList = (ListBox)target;
                this.playlistsList.PreviewKeyDown += new KeyEventHandler(this.listBox_PreviewKeyDown);
                return;

            case 5:
                this.genresLabel = (Label)target;
                return;

            case 6:
                this.genresList = (ListBox)target;
                this.genresList.PreviewKeyDown += new KeyEventHandler(this.listBox_PreviewKeyDown);
                return;

            case 7:
                this.artistsLabel = (Label)target;
                return;

            case 8:
                this.artistsList = (TreeListBox)target;
                return;

            case 9:
                this.drmMessage = (TextBlock)target;
                return;

            case 10:
                this.cancelButton = (Button)target;
                return;

            case 11:
                this.syncButton = (Button)target;
                return;
            }
            this._contentLoaded = true;
        }
示例#9
0
 public static void TreeListBoxPreviewKeyDown(TreeListBox sender, KeyEventArgs e)
 {
     if (((sender != null) && (e != null)) && (e.Key == Key.Space))
     {
         TreeListBoxInfo selectedItem = sender.SelectedItem as TreeListBoxInfo;
         if (selectedItem != null)
         {
             SelectableOptionViewModel dataItem = selectedItem.DataItem as SelectableOptionViewModel;
             dataItem.IsSelected = new bool?(dataItem.IsSelected.HasValue ? !dataItem.IsSelected.Value : false);
         }
         e.Handled = true;
     }
 }
示例#10
0
        public void TestItemsSourceCollectionNotifications()
        {
            AvalonTestRunner.RunInSTA(delegate
            {
                //populate sample data
                ObservableCollection <string> businessObjects =
                    new ObservableCollection <string>();
                businessObjects.Add("A");
                businessObjects.Add("AA");
                businessObjects.Add("AAA");
                businessObjects.Add("AAAA");

                TreeListBox treeListBox = new TreeListBox();
                treeListBox.ExposedGenerateItemsSource(businessObjects);
                Assert.AreEqual(4, treeListBox.Items.Count,
                                "Invalid number of items added");

                //add anew item and verify that this item was added to the items source
                businessObjects.Add("NewItem1");
                //check the Count
                Assert.AreEqual(5, treeListBox.Items.Count,
                                "Invalid number of items added");
                //check the position of the item
                Assert.AreEqual("NewItem1",
                                ((TreeListBoxInfo)treeListBox.Items[4]).DataItem,
                                "Item was added at an invalid index");

                //insert another item in the begining of the list
                businessObjects.Insert(1, "NewItem2");
                //check the Count
                Assert.AreEqual(6, treeListBox.Items.Count,
                                "Invalid number of items added");
                //check the position of the item
                Assert.AreEqual("NewItem2",
                                ((TreeListBoxInfo)treeListBox.Items[1]).DataItem,
                                "Item was added at an invalid index");

                //Check the remove
                businessObjects.RemoveAt(1);
                //check the Count
                Assert.AreEqual(5, treeListBox.Items.Count,
                                "Invalid number of items added");
                //validate that the item was deleted properly
                for (int i = 0; i < treeListBox.Items.Count; i++)
                {
                    Assert.AreNotEqual("NewItem2",
                                       ((TreeListBoxInfo)treeListBox.Items[i]).DataItem,
                                       "Item was removed from the wrong index");
                }
            });
        }
示例#11
0
        /////////////////////////////////////////////////////////////////////////////////////////////////////
        // PUBLIC PROCEDURES
        /////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Initializes a <see cref="IDataObject"/> based on the specified items.
        /// </summary>
        /// <param name="sourceControl">The source control that contains the items.</param>
        /// <param name="dataObject">The <see cref="IDataObject"/> to initialize.</param>
        /// <param name="items">The items to examine.</param>
        /// <returns>The <see cref="DragDropEffects"/> that specifies the allowed drag/drop effects for the <see cref="IDataObject"/>.</returns>
        /// <remarks>
        /// The default implementation of this method simply return <c>DragDropEffects.None</c>.
        /// Override this method to initialize the <see cref="IDataObject"/> with text and/or other data formats
        /// (such as <see cref="TreeListBox.ItemDataFormat"/> for supporting drag/drop),
        /// and to return an appropriate <c>DragDropEffects</c> result.
        /// </remarks>
        public override DragDropEffects InitializeDataObject(TreeListBox sourceControl, IDataObject dataObject, IEnumerable <object> items)
        {
            if (sourceControl == null)
            {
                throw new ArgumentNullException(nameof(sourceControl));
            }
            if (dataObject == null)
            {
                throw new ArgumentNullException(nameof(dataObject));
            }
            if (items == null)
            {
                throw new ArgumentNullException(nameof(items));
            }

            // Verify the source items
            foreach (var item in items)
            {
                if (!TryGetModelsFromItem(sourceControl, item, out var sourceCategoryModel, out _))
                {
                    // Quit if any item cannot be recognized
                    return(DragDropEffects.None);
                }
            }

            // Store the full paths to items in case we drop on the tree itself...
            // Each item needs to have a unique path, which comes from adapter GetPath() calls
            var fullPaths = JoinItemFullPaths(sourceControl, items);

            if (string.IsNullOrWhiteSpace(fullPaths))
            {
                return(DragDropEffects.None);
            }
            dataObject.SetData(TreeListBox.ItemDataFormat, fullPaths);

            // If there is one item, store its text so that it can be dropped elsewhere
            if (items.Count() == 1)
            {
                string text = GetDataObjectText(items.First());
                if (!string.IsNullOrEmpty(text))
                {
                    dataObject.SetData(DataFormats.Text, text);
                }
            }

            return(DragDropEffects.Move | DragDropEffects.Copy);
        }
示例#12
0
        /// <summary>
        /// Tries to get the category model for the specified <see cref="ToolboxTreeNodeModel"/>.
        /// </summary>
        /// <param name="toolboxControl">The <see cref="TreeListBox"/> control.</param>
        /// <param name="itemModel">The <see cref="ToolboxTreeNodeModel"/> to examine.</param>
        /// <param name="categoryModel">The resulting <see cref="CategoryTreeNodeModel"/>.</param>
        /// <returns>
        /// <c>true</c> if a result was found; otherwise, <c>false</c>.
        /// </returns>
        private bool TryGetCategory(TreeListBox toolboxControl, ToolboxTreeNodeModel itemModel, out CategoryTreeNodeModel categoryModel)
        {
            categoryModel = null;
            if (itemModel is CategoryTreeNodeModel localCategoryModel)
            {
                categoryModel = localCategoryModel;
                return(true);
            }

            var navigator = toolboxControl.GetItemNavigator(itemModel);

            if (navigator.GoToParent())
            {
                categoryModel = navigator.CurrentItem as CategoryTreeNodeModel;
                return(categoryModel != null);
            }

            return(false);
        }
示例#13
0
        /////////////////////////////////////////////////////////////////////////////////////////////////////
        // PUBLIC PROCEDURES
        /////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Initializes a <see cref="IDataObject"/> based on the specified items.
        /// </summary>
        /// <param name="sourceControl">The source control that contains the items.</param>
        /// <param name="dataObject">The <see cref="IDataObject"/> to initialize.</param>
        /// <param name="items">The items to examine.</param>
        /// <returns>The <see cref="DragDropEffects"/> that specifies the allowed drag/drop effects for the <see cref="IDataObject"/>.</returns>
        /// <remarks>
        /// The default implementation of this method simply return <c>DragDropEffects.None</c>.
        /// Override this method to initialize the <see cref="IDataObject"/> with text and/or other data formats
        /// (such as <see cref="TreeListBox.ItemDataFormat"/> for supporting drag/drop),
        /// and to return an appropriate <c>DragDropEffects</c> result.
        /// </remarks>
        public override DragDropEffects InitializeDataObject(TreeListBox sourceControl, IDataObject dataObject, IEnumerable <object> items)
        {
            if (sourceControl == null)
            {
                throw new ArgumentNullException("sourceControl");
            }
            if (dataObject == null)
            {
                throw new ArgumentNullException("dataObject");
            }
            if (items == null)
            {
                throw new ArgumentNullException("items");
            }

            // Store the full paths to items in case we drop on the tree itself...
            //   Each item needs to have a unique path, which comes from adapter GetPath() calls
            var fullPaths = new StringBuilder();

            foreach (var item in items)
            {
                fullPaths.AppendLine(sourceControl.GetFullPath(item));
            }
            if (fullPaths.Length > 0)
            {
                dataObject.SetData(TreeListBox.ItemDataFormat, fullPaths.ToString());
            }

            // If there is one item, store its text so that it can be dropped elsewhere
            if (items.Count() == 1)
            {
                var viewModel = items.First() as TreeNodeModel;
                if (viewModel != null)
                {
                    dataObject.SetData(DataFormats.Text, viewModel.Name);
                }
            }

            return(DragDropEffects.Move);
        }
示例#14
0
        /// <summary>
        /// Tries to get the category and control models for the specified item.
        /// </summary>
        /// <param name="toolboxControl">The <see cref="TreeListBox"/> control.</param>
        /// <param name="item">The item to examine.</param>
        /// <param name="categoryModel">The resulting <see cref="CategoryTreeNodeModel"/>.</param>
        /// <param name="controlModel">The resulting <see cref="ControlTreeNodeModel"/>.</param>
        /// <returns>
        /// <c>true</c> if results were found; otherwise, <c>false</c>.
        /// </returns>
        private bool TryGetModelsFromItem(TreeListBox toolboxControl, object item, out CategoryTreeNodeModel categoryModel, out ControlTreeNodeModel controlModel)
        {
            if (item is ControlTreeNodeModel localControlModel)
            {
                controlModel = localControlModel;
                return(TryGetCategory(toolboxControl, controlModel, out categoryModel));
            }
            else if (item is EmptyPlaceholderTreeNodeModel emptyPlaceholderModel)
            {
                controlModel = null;
                return(TryGetCategory(toolboxControl, emptyPlaceholderModel, out categoryModel));
            }
            else if (item is CategoryTreeNodeModel localCategoryModel)
            {
                controlModel  = null;
                categoryModel = localCategoryModel;
                return(true);
            }

            categoryModel = null;
            controlModel  = null;
            return(false);
        }
        /// <summary>
        /// Returns the item's text by which to match when searching.
        /// </summary>
        /// <param name="ownerControl">The owner control.</param>
        /// <param name="item">The item to examine.</param>
        /// <returns>The item's string search text.</returns>
        public override string GetSearchText(TreeListBox ownerControl, object item)
        {
            var model = item as TreeNodeModel;

            return(model != null ? model.Name: null);
        }
示例#16
0
        /// <summary>
        /// Notifies that a drop event occurred over a target item and requests that appropriate updates are made to the supplied <c>DragEventArgs</c>.
        /// </summary>
        /// <param name="e">The <see cref="DragEventArgs"/> whose effects should be updated.</param>
        /// <param name="targetControl">The target control, over which the event occurred</param>
        /// <param name="targetItem">The target item, which could be <see langword="null"/> if dragging below the last tree item.</param>
        /// <param name="dropArea">A <see cref="TreeItemDropArea"/> indicating the drop area over the target item.</param>
        /// <remarks>
        /// The default implementation of this method sets the <c>e.Effects</c> to <c>DragDropEffects.None</c> and takes no further action.
        /// Override this method if you wish to support dropping and add logic to properly handle the dragged data.
        /// </remarks>
        public override void OnDrop(DragEventArgs e, TreeListBox targetControl, object targetItem, TreeItemDropArea dropArea)
        {
            var originalEffects = e.Effects;

            e.Effects = DragDropEffects.None;

            // If the drag is over an item and there is item data present...
            var targetModel = targetItem as TreeNodeModel;

            if ((targetModel != null) && (dropArea != TreeItemDropArea.None) && (e.Data.GetDataPresent(TreeListBox.ItemDataFormat)))
            {
                // Resolve the real target item (in case the drop area is above or below the target item)
                var targetDropIndex = targetModel.Children.Count;
                switch (dropArea)
                {
                case TreeItemDropArea.Before:
                case TreeItemDropArea.After:
                    var nav = targetControl.GetItemNavigator(targetItem);
                    if (nav != null)
                    {
                        var targetChildModel = targetModel;
                        var targetChildItem  = targetItem;

                        if (!nav.GoToParent())
                        {
                            return;
                        }
                        targetItem  = nav.CurrentItem;
                        targetModel = targetItem as TreeNodeModel;
                        if (targetModel == null)
                        {
                            return;
                        }

                        var index = targetModel.Children.IndexOf(targetChildModel);
                        if (index != -1)
                        {
                            targetDropIndex = index + (dropArea == TreeItemDropArea.After ? 1 : 0);
                        }
                    }
                    break;
                }

                // Get the items
                var fullPaths = e.Data.GetData(TreeListBox.ItemDataFormat) as string;
                if (!string.IsNullOrEmpty(fullPaths))
                {
                    // Locate items based on full path
                    var items = new List <object>();
                    foreach (var fullPath in fullPaths.Split(new char[] { '\r', '\n' }))
                    {
                        if (!string.IsNullOrEmpty(fullPath))
                        {
                            var item = targetControl.GetItemByFullPath(fullPath);
                            if (item != null)
                            {
                                items.Add(item);
                            }
                        }
                    }

                    if (items.Count > 0)
                    {
                        // Check each item and validate that various drop operations are allowed before actually executing the drop
                        foreach (var item in items)
                        {
                            if (item == targetItem)
                            {
                                MessageBox.Show("Cannot drop an item on itself.", "Drag and Drop", MessageBoxButton.OK);
                                return;
                            }
                            else
                            {
                                var nav = targetControl.GetItemNavigator(item);
                                if (nav == null)
                                {
                                    MessageBox.Show("Cannot drop from a different control.", "Drag and Drop", MessageBoxButton.OK);
                                    return;
                                }
                                else
                                {
                                    if (nav.GoToCommonAncestor(targetItem))
                                    {
                                        if (nav.CurrentItem == item)
                                        {
                                            MessageBox.Show("Cannot drop onto a descendant item.", "Drag and Drop", MessageBoxButton.OK);
                                            return;
                                        }
                                    }
                                }
                            }
                        }

                        // Only support a single effect (you could add support for other effects like Copy if the Ctrl key is down here)
                        if ((originalEffects & DragDropEffects.Move) == DragDropEffects.Move)
                        {
                            e.Effects = DragDropEffects.Move;
                            e.Handled = true;
                        }

                        // Move items
                        foreach (var item in items)
                        {
                            var nav = targetControl.GetItemNavigator(item);
                            if (nav.GoToParent())
                            {
                                var itemModel   = item as TreeNodeModel;
                                var parentModel = nav.CurrentItem as TreeNodeModel;
                                if ((itemModel != null) && (parentModel != null))
                                {
                                    var index = parentModel.Children.IndexOf(itemModel);
                                    if (index != -1)
                                    {
                                        if ((parentModel == targetModel) && (index < targetDropIndex))
                                        {
                                            targetDropIndex--;
                                        }

                                        parentModel.Children.RemoveAt(index);
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                                else
                                {
                                    break;
                                }

                                targetModel.Children.Insert(Math.Max(0, Math.Min(targetModel.Children.Count, targetDropIndex++)), itemModel);
                                targetModel.IsExpanded = true;

                                // Focus the last item
                                if (items[items.Count - 1] == item)
                                {
                                    targetControl.FocusItem(itemModel);
                                }
                            }
                        }
                    }
                }
            }
        }
示例#17
0
        /// <summary>
        /// Gets an enumerable of all dragged items.
        /// </summary>
        /// <param name="dataObject">The <see cref="IDataObject"/> which defines the dragged items.</param>
        /// <param name="control">The control from which items will be derived.</param>
        /// <returns>Returns an enumerable of all dragged items which will be empty if no items were found.</returns>
        internal static IEnumerable <ToolboxTreeNodeModel> GetDraggedModels(IDataObject dataObject, TreeListBox control)
        {
            string format = TreeListBox.ItemDataFormat;

            if (dataObject.GetDataPresent(format))
            {
                string data = dataObject.GetData(format) as string;
                if (!string.IsNullOrWhiteSpace(data))
                {
                    foreach (var fullPath in SplitItemFullPaths(data))
                    {
                        if (control.GetItemByFullPath(fullPath) is ToolboxTreeNodeModel itemModel)
                        {
                            yield return(itemModel);
                        }
                    }
                }
            }
        }
示例#18
0
        /// <summary>
        /// Notifies that a drop event occurred over a target item and requests that appropriate updates are made to the supplied <c>DragEventArgs</c>.
        /// </summary>
        /// <param name="e">The <see cref="DragEventArgs"/> whose effects should be updated.</param>
        /// <param name="targetControl">The target control, over which the event occurred</param>
        /// <param name="targetItem">The target item, which could be <see langword="null"/> if dragging below the last tree item.</param>
        /// <param name="dropArea">A <see cref="TreeItemDropArea"/> indicating the drop area over the target item.</param>
        /// <remarks>
        /// The default implementation of this method sets the <c>e.Effects</c> to <c>DragDropEffects.None</c> and takes no further action.
        /// Override this method if you wish to support dropping and add logic to properly handle the dragged data.
        /// </remarks>
        public override void OnDrop(DragEventArgs e, TreeListBox targetControl, object targetItem, TreeItemDropArea dropArea)
        {
            var originalEffects = e.Effects;

            e.Effects = DragDropEffects.None;

            // If the drag is over an item and there is item data present...
            var targetModel = targetItem as ToolboxTreeNodeModel;

            if ((targetModel != null) && (dropArea != TreeItemDropArea.None) && (e.Data.GetDataPresent(TreeListBox.ItemDataFormat)))
            {
                // Resolve the real target item (in case the drop area is above or below the target item)
                var targetDropIndex = targetModel.Children.Count;
                switch (dropArea)
                {
                case TreeItemDropArea.Before:
                case TreeItemDropArea.After:
                    // When dropping before or after, a new node will be inserted as a child to the parent of the target
                    var nav = targetControl.GetItemNavigator(targetItem);
                    if (nav != null)
                    {
                        // Cache the original target
                        var targetChildModel = targetModel;

                        // Quit if unable to move to navigate to the parent
                        if (!nav.GoToParent())
                        {
                            return;
                        }

                        // Update the target item to be the parent of the original target
                        targetItem  = nav.CurrentItem;
                        targetModel = targetItem as ToolboxTreeNodeModel;

                        // Quit if the new target is not the expected model
                        if (targetModel == null)
                        {
                            return;
                        }

                        // Resolve index of the new node based on whether it should be before
                        // or after the original target.
                        var index = targetModel.Children.IndexOf(targetChildModel);
                        if (index != -1)
                        {
                            targetDropIndex = index + (dropArea == TreeItemDropArea.After ? 1 : 0);
                        }
                    }
                    break;
                }

                // Resolve the category for the drop target
                if (!TryGetCategory(targetControl, targetModel, out var targetCategoryModel))
                {
                    MessageBox.Show("Unable to determine the drop category.", "Drag and Drop", MessageBoxButton.OK);
                    return;
                }

                // Get the dragged controls (only control nodes are currently supported)
                List <ControlTreeNodeModel> sourceControlModels = GetDraggedModels(e.Data, targetControl)
                                                                  .OfType <ControlTreeNodeModel>()
                                                                  .ToList();
                if (sourceControlModels.Count > 0)
                {
                    // Check each item and validate that various drop operations are allowed before actually executing the drop
                    foreach (var sourceModel in sourceControlModels)
                    {
                        if (sourceModel == targetModel)
                        {
                            MessageBox.Show("Cannot drop an item on itself.", "Drag and Drop", MessageBoxButton.OK);
                            return;
                        }
                        else
                        {
                            var nav = targetControl.GetItemNavigator(sourceModel);
                            if (nav == null)
                            {
                                MessageBox.Show("Cannot drop from a different control.", "Drag and Drop", MessageBoxButton.OK);
                                return;
                            }
                            else
                            {
                                if (nav.GoToCommonAncestor(targetItem))
                                {
                                    if (nav.CurrentItem == sourceModel)
                                    {
                                        MessageBox.Show("Cannot drop onto a descendant item.", "Drag and Drop", MessageBoxButton.OK);
                                        return;
                                    }
                                }
                            }
                        }
                    }

                    // Only support a single effect (you could add support for other effects like Copy if the Ctrl key is down here)
                    if ((originalEffects & DragDropEffects.Move) == DragDropEffects.Move)
                    {
                        e.Effects = DragDropEffects.Move;
                        e.Handled = true;
                    }
                    else if ((originalEffects & DragDropEffects.Copy) == DragDropEffects.Copy)
                    {
                        e.Effects = DragDropEffects.Copy;
                        e.Handled = true;
                    }

                    if (IsFavoritesCategory(targetCategoryModel))
                    {
                        // Controls dragged into favorites category will not actually be moved. They will be added as favorites.
                        foreach (var sourceControlModel in sourceControlModels)
                        {
                            sourceControlModel.IsFavorite = true;
                        }
                    }
                    else
                    {
                        // Complete operation
                        bool isMove = e.Effects == DragDropEffects.Move;
                        foreach (var sourceControlModel in sourceControlModels)
                        {
                            // Resolve the source category of the dragged control
                            if (!TryGetCategory(targetControl, sourceControlModel, out var sourceCategoryModel))
                            {
                                break;
                            }

                            if (isMove)
                            {
                                // Remove the control from the original category
                                var index = sourceCategoryModel.Children.IndexOf(sourceControlModel);
                                if (index != -1)
                                {
                                    if ((sourceCategoryModel == targetCategoryModel) && (index < targetDropIndex))
                                    {
                                        targetDropIndex--;
                                    }

                                    sourceCategoryModel.Children.RemoveAt(index);
                                }
                                else
                                {
                                    // Quit processing if any source cannot be located
                                    break;
                                }

                                // Add the control to the new category (may be the same as the source if it was repositioned)
                                int resolvedTargetDropIndex = Math.Max(0, Math.Min(targetCategoryModel.Children.Count, targetDropIndex++));
                                targetCategoryModel.Children.Insert(resolvedTargetDropIndex, sourceControlModel);
                                targetCategoryModel.IsExpanded = true;

                                // Focus the last item that was moved
                                if (sourceControlModels[sourceControlModels.Count - 1] == sourceControlModel)
                                {
                                    // Must dispatch the focus changes to allow the view to update based on changes in the models
                                    Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => {
                                        targetControl.FocusItem(sourceControlModel);
                                    }), DispatcherPriority.Normal);
                                }
                            }
                        }
                    }
                }
            }
        }
示例#19
0
        /// <summary>
        /// Notifies that a drag event occurred over a target item, requests that appropriate updates are made to the supplied <c>DragEventArgs</c>,
        /// and requests that the allowed drop area is returned for visual target feedback.
        /// </summary>
        /// <param name="e">The <see cref="DragEventArgs"/> whose effects should be updated.</param>
        /// <param name="targetControl">The target control, over which the event occurred</param>
        /// <param name="targetItem">The target item, which could be <see langword="null"/> if dragging below the last tree item.</param>
        /// <param name="dropArea">A <see cref="TreeItemDropArea"/> indicating the drop area over the target item.</param>
        /// <returns>
        /// A <see cref="TreeItemDropArea"/> indicating the allowed drop area, which will be used for visual feedback to the end user.
        /// Return <c>TreeItemDropArea.None</c> for no visual feedback.
        /// </returns>
        /// <remarks>
        /// The default implementation of this method sets the <c>e.Effects</c> to <c>DragDropEffects.None</c> and returns that no drop area is allowed.
        /// Override this method if you wish to support dropping and add logic to properly handle the dragged data.
        /// </remarks>
        public override TreeItemDropArea OnDragOver(DragEventArgs e, TreeListBox targetControl, object targetItem, TreeItemDropArea dropArea)
        {
            // If the drag is over an item, item data present, and the drop target is recognized...
            if ((dropArea != TreeItemDropArea.None) &&
                (e.Data.GetDataPresent(TreeListBox.ItemDataFormat)) &&
                (TryGetModelsFromItem(targetControl, targetItem, out var targetCategoryModel, out _)))
            {
                // Locate the dragged model. If multiple objects were selected, only the first object is used for reference.
                // The dragged item must be defined in the target control for the drag operation to be allowed.
                var sourceItem = GetDraggedModels(e.Data, targetControl).FirstOrDefault();
                if ((sourceItem != null) && (TryGetModelsFromItem(targetControl, sourceItem, out var sourceCategoryModel, out _)))
                {
                    if (IsFavoritesCategory(sourceCategoryModel))
                    {
                        // Dragging from the "Favorites" category is not supported within the Toolbox control. Favorites can only
                        // be dragged outside of the control (i.e. to the designer surface).
                        e.Effects = DragDropEffects.None;
                        e.Handled = true;
                    }
                    else if (IsFavoritesCategory(targetCategoryModel))
                    {
                        // Dropping on the "Favorites" category will only change if the control is a favorite and will not
                        // alter the location of the source control in the toolbox, so use the 'Copy' effect.
                        if ((e.AllowedEffects & DragDropEffects.Copy) == DragDropEffects.Copy)
                        {
                            e.Effects = DragDropEffects.Copy;
                            e.Handled = true;
                        }
                    }
                    else
                    {
                        // Controls cannot exist in more than one category, so only move effect is allowed
                        if ((e.AllowedEffects & DragDropEffects.Move) == DragDropEffects.Move)
                        {
                            e.Effects = DragDropEffects.Move;
                            e.Handled = true;
                        }
                    }

                    if ((e.Handled) && (e.Effects != DragDropEffects.None))
                    {
                        // TreeItems can be dropped 'Before', 'On', or 'After' a target node, but drop targets may not support
                        // all of these scenarios. Coerce the drop area, as needed, based on the target node.

                        if (targetItem is CategoryTreeNodeModel)
                        {
                            // Since controls can only be children to a category, not siblings, coerce all drops to 'On'
                            dropArea = TreeItemDropArea.On;
                        }
                        else if (targetItem is EmptyPlaceholderTreeNodeModel)
                        {
                            // When the control is dropped, the empty placeholder will be remove and the dropped control
                            // will be added as first child to the category, so coerce all drops to 'Before' the placeholder.
                            dropArea = TreeItemDropArea.Before;
                        }
                        else if ((targetItem is ControlTreeNodeModel) && (dropArea == TreeItemDropArea.On))
                        {
                            // A control cannot have children, so coerce dropping 'On' a control to 'After' (i.e. next sibling)
                            dropArea = TreeItemDropArea.After;
                        }

                        return(dropArea);
                    }
                }
            }

            e.Effects = DragDropEffects.None;
            return(TreeItemDropArea.None);
        }
示例#20
0
        public void TestPopulationOfChildren()
        {
            AvalonTestRunner.RunInSTA(delegate
            {
                //create sample data
                MockHierarchalObject dataSource =
                    new MockHierarchalObject("A",
                                             new List <MockHierarchalObject>(
                                                 new MockHierarchalObject[]
                {
                    //children
                    new MockHierarchalObject(
                        "child1 of A"),
                    new MockHierarchalObject(
                        "child2 of A"),
                    new MockHierarchalObject(
                        "child3 of A"),
                }));

                //prepare the parent collection
                TreeListBox parentControl         = new TreeListBox();
                parentControl.ChildItemSourcePath = "Children";
                parentControl.ExposedGenerateItemsSource(new MockHierarchalObject[]
                {
                    new MockHierarchalObject(
                        "First, item with no children")
                    ,
                    //add a simple item that has no children
                    dataSource,
                    //add the item that has children to test on
                    new MockHierarchalObject(
                        "Last, item with no children")
                });
                Assert.AreEqual(3, parentControl.Items.Count, "Invalid number of items");
                //create an item to test
                TreeListBoxItem item = new TreeListBoxItem(parentControl);
                item.ExposePrepareItem(parentControl.Items[1] as TreeListBoxInfo);
                //pass the info that was create for the item that has children

                //expand the item this should result in the items source of the parent include the children
                item.IsExpanded = true;
                //3 root nodes and 3 children are suppose to be in the list
                Assert.AreEqual(3 + 3, parentControl.Items.Count,
                                "Invalid number of items");

                //check that the items where create in the right indeces
                Assert.AreEqual("child1 of A",
                                ((MockHierarchalObject)
                                 ((TreeListBoxInfo)parentControl.Items[2]).DataItem).Text,
                                "Child Item was placed in the wrong index");
                //validate that the last item(which is index to of the root nodes) of the root nodes has been moved to the proper index
                //2 is the index in the root nodes, 3 is the count of the children, so the last item should have moved to index 5
                Assert.AreEqual("Last, item with no children",
                                ((MockHierarchalObject)
                                 ((TreeListBoxInfo)parentControl.Items[2 + 3]).DataItem).
                                Text,
                                "Root Item was placed in the wrong index");

                //validate that the level of the items has been incremented
                //start from index 2, since the children are place at index 2
                for (int i = 2; i < 3 + 2; i++)
                {
                    Assert.AreEqual(1, ((TreeListBoxInfo)parentControl.Items[i]).Level,
                                    "Invalid level set for child nodes");
                }

                //Validate the Collapse
                item.IsExpanded = false;

                //all children should be dropped
                Assert.AreEqual(3, parentControl.Items.Count, "Invalid number of items");

                //check that the indeces of the items is back to normal
                Assert.AreEqual("First, item with no children",
                                ((MockHierarchalObject)
                                 ((TreeListBoxInfo)parentControl.Items[0]).DataItem).Text,
                                "Root Item was placed in the wrong index");
                Assert.AreEqual("A",
                                ((MockHierarchalObject)
                                 ((TreeListBoxInfo)parentControl.Items[1]).DataItem).Text,
                                "Root Item was placed in the wrong index");
                Assert.AreEqual("Last, item with no children",
                                ((MockHierarchalObject)
                                 ((TreeListBoxInfo)parentControl.Items[2]).DataItem).Text,
                                "Root Item was placed in the wrong index");
            });
        }
        /// <summary>
        /// Returns whether the specified item is currently being edited.
        /// </summary>
        /// <param name="ownerControl">The owner control.</param>
        /// <param name="item">The item to examine.</param>
        /// <returns>
        /// <c>true</c> if the specified item is currently being edited; otherwise, <c>false</c>.
        /// </returns>
        public override bool GetIsEditing(TreeListBox ownerControl, object item)
        {
            var model = item as TreeNodeModel;

            return(model != null ? model.IsEditing : false);
        }
        /////////////////////////////////////////////////////////////////////////////////////////////////////
        // PUBLIC PROCEDURES
        /////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Returns an <see cref="IEnumerable"/> that will be used to provide child items for the specified parent item.
        /// </summary>
        /// <param name="ownerControl">The owner control.</param>
        /// <param name="item">The item to examine.</param>
        /// <returns>An <see cref="IEnumerable"/> that will be used to provide child items for the specified parent item.</returns>
        public override IEnumerable GetChildren(TreeListBox ownerControl, object item)
        {
            var model = item as TreeNodeModel;

            return(model != null ? model.Children : null);
        }
示例#23
0
        /// <summary>
        /// Notifies that a drag event occurred over a target item, requests that appropriate updates are made to the supplied <c>DragEventArgs</c>,
        /// and requests that the allowed drop area is returned for visual target feedback.
        /// </summary>
        /// <param name="e">The <see cref="DragEventArgs"/> whose effects should be updated.</param>
        /// <param name="targetControl">The target control, over which the event occurred</param>
        /// <param name="targetItem">The target item, which could be <see langword="null"/> if dragging below the last tree item.</param>
        /// <param name="dropArea">A <see cref="TreeItemDropArea"/> indicating the drop area over the target item.</param>
        /// <returns>
        /// A <see cref="TreeItemDropArea"/> indicating the allowed drop area, which will be used for visual feedback to the end user.
        /// Return <c>TreeItemDropArea.None</c> for no visual feedback.
        /// </returns>
        /// <remarks>
        /// The default implementation of this method sets the <c>e.Effects</c> to <c>DragDropEffects.None</c> and returns that no drop area is allowed.
        /// Override this method if you wish to support dropping and add logic to properly handle the dragged data.
        /// </remarks>
        public override TreeItemDropArea OnDragOver(DragEventArgs e, TreeListBox targetControl, object targetItem, TreeItemDropArea dropArea)
        {
            // If the drag is over an item and there is item data present...
            if ((targetItem != null) && (dropArea != TreeItemDropArea.None) && (e.Data.GetDataPresent(TreeListBox.ItemDataFormat)))
            {
                var fullPaths = e.Data.GetData(TreeListBox.ItemDataFormat) as string;
                if (!string.IsNullOrEmpty(fullPaths))
                {
                    // Locate the first item based on full path
                    object firstItem = null;
                    foreach (var fullPath in fullPaths.Split(new char[] { '\r', '\n' }))
                    {
                        if (!string.IsNullOrEmpty(fullPath))
                        {
                            var item = targetControl.GetItemByFullPath(fullPath);
                            if (item != null)
                            {
                                firstItem = item;
                                break;
                            }
                        }
                    }

                    if (firstItem != null)
                    {
                        // Ensure that the first item is already in the target control (nav will be null if not)... if allowing drag/drop onto external
                        //   controls, you cannot use the item navigator and must rely on your own item hierarchy logic
                        var firstItemNav = targetControl.GetItemNavigator(firstItem);
                        if (firstItemNav != null)
                        {
                            // Only support a single effect (you could add support for other effects like Copy if the Ctrl key is down here)
                            if ((e.AllowedEffects & DragDropEffects.Move) == DragDropEffects.Move)
                            {
                                e.Effects = DragDropEffects.Move;
                                e.Handled = true;
                            }

                            switch (e.Effects)
                            {
                            case DragDropEffects.Move:
                                // Coerce the resulting drop-area so that if dragging 'after' an item that has a next sibling, the drop area
                                //   becomes 'on' the item instead... can still get between the items by dragging 'before' the next sibling in this scenario
                                if (dropArea == TreeItemDropArea.After)
                                {
                                    var targetItemNav = targetControl.GetItemNavigator(targetItem);
                                    if ((targetItemNav != null) && (targetItemNav.GoToNextSibling()))
                                    {
                                        dropArea = TreeItemDropArea.On;
                                    }
                                }

                                return(dropArea);
                            }
                        }
                    }
                }
            }

            e.Effects = DragDropEffects.None;
            return(TreeItemDropArea.None);
        }
        /// <summary>
        /// Returns whether the specified item is capable of being selected.
        /// </summary>
        /// <param name="ownerControl">The owner control.</param>
        /// <param name="item">The item to examine.</param>
        /// <returns>
        /// <c>true</c> if the specified item is capable of being selected; otherwise, <c>false</c>.
        /// </returns>
        public override bool GetIsSelectable(TreeListBox ownerControl, object item)
        {
            var model = item as TreeNodeModel;

            return(model != null ? model.IsSelectable : true);
        }
示例#25
0
        public void TestPopulationOfChildrenFromNotifications()
        {
            AvalonTestRunner.RunInSTA(delegate
            {
                //children collection
                ObservableCollection <MockHierarchalObject> childNodes =
                    new ObservableCollection <MockHierarchalObject>(
                        new List <MockHierarchalObject>(new MockHierarchalObject[]
                {
                    //children
                    new MockHierarchalObject(
                        "child1 of A"),
                    new MockHierarchalObject(
                        "child2 of A"),
                    new MockHierarchalObject(
                        "child3 of A"),
                }));

                //create sample data
                MockHierarchalObject dataSource =
                    new MockHierarchalObject("A", childNodes);

                //prepare the parent collection
                TreeListBox parentControl         = new TreeListBox();
                parentControl.ChildItemSourcePath = "Children";
                parentControl.ExposedGenerateItemsSource(new MockHierarchalObject[]
                {
                    new MockHierarchalObject(
                        "First, item with no children")
                    ,
                    //add a simple item that has no children
                    dataSource,
                    //add the item that has children to test on
                    new MockHierarchalObject(
                        "Last, item with no children")
                });

                Assert.AreEqual(3, parentControl.Items.Count, "Invalid number of items");
                //create an item to test
                TreeListBoxItem item = new TreeListBoxItem(parentControl);
                item.ExposePrepareItem(parentControl.Items[1] as TreeListBoxInfo);
                //pass the info that was create for the item that has children

                //expand the item this should result in the items source of the parent include the children
                item.IsExpanded = true;
                //3 root nodes and 3 children are suppose to be in the list
                Assert.AreEqual(3 + 3, parentControl.Items.Count,
                                "Invalid number of items");

                //add a new item to child collection and check if it is added
                childNodes.Add(new MockHierarchalObject("child4 of A"));
                //3 root nodes and 3 + 1(which is the new one) children are suppose to be in the list
                Assert.AreEqual(3 + childNodes.Count, parentControl.Items.Count,
                                "Invalid number of items");
                //check the index of the new item in the flat list
                //1 is the index of the container item, and 4 is the count of the children
                Assert.AreEqual("child4 of A",
                                ((MockHierarchalObject)
                                 ((TreeListBoxInfo)parentControl.Items[1 + 4]).DataItem).
                                Text,
                                "Item was not added in the right index");

                //check that the insert in a specific index
                childNodes.Insert(2, new MockHierarchalObject("inserted child of A"));
                Assert.AreEqual(3 + childNodes.Count, parentControl.Items.Count,
                                "Invalid number of items");
                //check that the insert was done in the right index(where 1 is the parent index and 2 is the index in the children collection)
                Assert.AreEqual("inserted child of A",
                                ((MockHierarchalObject)
                                 ((TreeListBoxInfo)parentControl.Items[1 + 3]).DataItem).
                                Text,
                                "Item was not added in the right index");

                //check the remove of items
                childNodes.RemoveAt(2);
                //check the Count
                Assert.AreEqual(3 + childNodes.Count, parentControl.Items.Count,
                                "Invalid number of items added");
                //validate that the item was deleted properly
                for (int i = 0; i < parentControl.Items.Count; i++)
                {
                    Assert.AreNotEqual("inserted child of A",
                                       ((MockHierarchalObject)
                                        ((TreeListBoxInfo)parentControl.Items[i]).
                                        DataItem).Text,
                                       "Item was removed from the wrong index");
                }

                //check that if we collapse the items no children are add
                item.IsExpanded = false;
                //check that the items where collapsed
                Assert.AreEqual(3, parentControl.Items.Count,
                                "Invalid number of items after collapse item");

                childNodes.Add(new MockHierarchalObject("Test collapse"));
                //check that the item was not added to the flat list since the item is collapsed
                Assert.AreEqual(3, parentControl.Items.Count,
                                "Invalid number of items after collapse item");

                //check that when you re expand the item all items are generated
                item.IsExpanded = true;
                Assert.AreEqual(3 + childNodes.Count, parentControl.Items.Count,
                                "Invalid number of items after collapse item");
            });
        }