public void Expand() { if (!IsEnabled()) { throw new ElementNotEnabledException(); } MultiSelectTreeViewItem treeViewItem = (MultiSelectTreeViewItem)Owner; if (!treeViewItem.HasItems) { throw new InvalidOperationException("Cannot expand because item has no children."); } treeViewItem.IsExpanded = true; }
/// <summary> /// Overridden because original wpf tree does show the expander button and the contents of the /// header as children, too. That was requested by the users. /// </summary> /// <returns>Returns a list of children.</returns> protected override List <AutomationPeer> GetChildrenCore() { //System.Diagnostics.Trace.WriteLine("MultiSelectTreeViewItemAutomationPeer.GetChildrenCore()"); MultiSelectTreeViewItem owner = (MultiSelectTreeViewItem)Owner; List <AutomationPeer> children = new List <AutomationPeer>(); var button = owner.Template.FindName("Expander", owner) as ToggleButton; AddAutomationPeer(children, button); //System.Diagnostics.Trace.WriteLine("- Adding ToggleButton, " + (button == null ? "IS" : "is NOT") + " null, now " + children.Count + " items"); var contentPresenter = GetContentPresenter(owner); if (contentPresenter != null) { int childrenCount = VisualTreeHelper.GetChildrenCount(contentPresenter); for (int i = 0; i < childrenCount; i++) { var child = VisualTreeHelper.GetChild(contentPresenter, i) as UIElement; AddAutomationPeer(children, child); //System.Diagnostics.Trace.WriteLine("- Adding child UIElement, " + (child == null ? "IS" : "is NOT") + " null, now " + children.Count + " items"); } } ItemCollection items = owner.Items; for (int i = 0; i < items.Count; i++) { MultiSelectTreeViewItem treeViewItem = owner.ItemContainerGenerator.ContainerFromIndex(i) as MultiSelectTreeViewItem; AddAutomationPeer(children, treeViewItem); //System.Diagnostics.Trace.WriteLine("- Adding MultiSelectTreeViewItem, " + (treeViewItem == null ? "IS" : "is NOT") + " null, now " + children.Count + " items"); } if (children.Count > 0) { //System.Diagnostics.Trace.WriteLine("MultiSelectTreeViewItemAutomationPeer.GetChildrenCore(): returning " + children.Count + " children"); //for (int i = 0; i < children.Count; i++) //{ // System.Diagnostics.Trace.WriteLine("- Item " + i + " " + (children[i] == null ? "IS" : "is NOT") + " null"); //} return(children); } //System.Diagnostics.Trace.WriteLine("MultiSelectTreeViewItemAutomationPeer.GetChildrenCore(): returning null"); return(null); }
private bool DealHover( ItemsControl targetItemsControl, IList <TestModel> targetCollection, int targetIndex, IList <TestModel> sourceCollection, int sourceIndex, TestModel sourceItem, int newGroupIndex, MultiSelectTreeViewItem overlapContainer, ref MultiSelectTreeViewItem lastOverlapContainer, ref DateTime startOverlapTime) { if (!(targetItemsControl is MultiSelectTreeView)) { return(false); } if (lastOverlapContainer != overlapContainer) { lastOverlapContainer = overlapContainer; startOverlapTime = DateTime.Now; } if ((DateTime.Now - startOverlapTime).TotalMilliseconds > 1200) { var targetItem = targetCollection[targetIndex]; var group = new TestModel { Name = "New Group", IsGroup = true }; group.ModelCollection.Add(targetItem); group.ModelCollection.Add(sourceItem); targetCollection.RemoveAt(targetIndex); targetCollection.Insert(targetIndex, group); sourceCollection.RemoveAt(sourceIndex); var newGroupGenerator = (ContainerFromIndex(targetItemsControl, newGroupIndex) as ItemsControl).ItemContainerGenerator; CheckNewGroupContainerGenerator(newGroupGenerator); lastOverlapContainer = null; } return(true); }
public void SetValue(string value) { try { if (String.IsNullOrWhiteSpace(value)) { return; } string[] ids = value.Split(new[] { ';' }); object obj; if (ids.Length > 0 && ids[0] == "Context") { MultiSelectTreeViewItem treeViewItem = (MultiSelectTreeViewItem)Owner; obj = treeViewItem.DataContext; } else { obj = Owner; } if (ids.Length < 2) { requestedValue = obj.ToString(); } else { Type type = obj.GetType(); PropertyInfo pi = type.GetProperty(ids[1]); requestedValue = pi.GetValue(obj, null).ToString(); } } catch (Exception ex) { requestedValue = ex.ToString(); } }
private void CheckNewGroupContainerGenerator(ItemContainerGenerator newGroupGenerator) { if (newGroupGenerator.Status < GeneratorStatus.ContainersGenerated) { EventHandler handler = null; handler = (s, e) => { var generator = (ItemContainerGenerator)s; if (_draggingContainer == null) { generator.StatusChanged -= handler; } else { if (generator.Status == GeneratorStatus.ContainersGenerated) { _draggingContainer = generator.ContainerFromIndex(1) as MultiSelectTreeViewItem; if (_draggingContainer != null) { _draggingContainer.Focus(); _draggingContainer.Opacity = 0.2; } generator.StatusChanged -= handler; } } }; newGroupGenerator.StatusChanged += handler; } else { _draggingContainer = newGroupGenerator.ContainerFromIndex(1) as MultiSelectTreeViewItem; } }
/// <summary> /// Select all nodes between the two nodes given in the arguments. The two nodes might be given in arbitrary order and at arbitrary levels. /// </summary> /// <param name="item1">One node.</param> /// <param name="item2">The other node.</param> /// <param name="includingIndirectChildNodes"></param> public static void SelectAllNodesInbetween(MultiSelectTreeViewItem item1, MultiSelectTreeViewItem item2, bool includingIndirectChildNodes) { int level1 = item1.GetDepth(); int level2 = item2.GetDepth(); // swap item1 and item2, so that item2 is the item with the higher level if (level1 > level2) { var hi = item1; var hl = level1; item1 = item2; level1 = level2; item2 = hi; level2 = hl; } // get the parent node of item2, that is on the same level than item1 var item2OnLevel1 = item2; // for (int l = level2 - 1; l >= level1; --l) item2OnLevel1 = (MultiSelectTreeViewItem)item2OnLevel1.ParentItemsControl; // to determine which node is the first node and which the last node, find // the common anchestor of both nodes var it1 = item1; var it2 = item2OnLevel1; while (it1.ParentItemsControl != it2.ParentItemsControl) { it1 = it1.ParentItemsControl as MultiSelectTreeViewItem; it2 = it2.ParentItemsControl as MultiSelectTreeViewItem; } // now we can determine which node is first and which last // if both are identical, then item1 is the first item, since // parent nodes comes first compared to child nodes var commonParent = it1.ParentItemsControl; int idx1 = commonParent.ItemContainerGenerator.IndexFromContainer(it1); int idx2 = commonParent.ItemContainerGenerator.IndexFromContainer(it2); bool item1IsFirst = idx1 <= idx2; // Swap so that item1 gets the first item if (!item1IsFirst) { var hi = item1; var hl = level1; var hh = it1; var hx = idx1; item1 = item2; level1 = level2; it1 = it2; idx1 = idx2; item2 = hi; level2 = hl; it2 = hh; idx2 = hx; } // if item1 and item2 share the same anchestor, select from item1 to items if (item1.ParentItemsControl == commonParent && item2.ParentItemsControl == commonParent) { SelectAllChildNodesBetweenIndices(commonParent, idx1, idx2); } else { // first go down to the common anchestor, and then up var current = item1; current.IsSelected = true; var parent = current.ParentItemsControl; while (parent != commonParent) { int idx = parent.ItemContainerGenerator.IndexFromContainer(current); SelectAllChildNodesBetweenIndexAndEnd(parent, idx + 1); current = parent as MultiSelectTreeViewItem; parent = current.ParentItemsControl; } // now select all items between idx1+1 and idx2-1 (including all childs) SelectAllChildNodesBetweenIndices(commonParent, idx1 + 1, idx2 - 1); // last select from item2 downwards to the common anchestor current = item2; parent = current.ParentItemsControl; while (parent != commonParent) { int idx = parent.ItemContainerGenerator.IndexFromContainer(current); SelectAllChildNodesBetweenStartAndIndex(parent, idx); current = parent as MultiSelectTreeViewItem; parent = current.ParentItemsControl; } current.IsSelected = true; } }
/// <summary> /// Retrieve the subsequent node that is at the same level. /// </summary> /// <param name="item">The node starting with you want to retrieve the subsequent one.</param> /// <returns>Null if there is no subsequent node at the same level.</returns> public static MultiSelectTreeViewItem GetNextNodeAtSameLevel(MultiSelectTreeViewItem item) { if (item == null) return null; MultiSelectTreeViewItem nextNodeAtSameLevel = null; ItemsControl parentControl = item.ParentItemsControl; if (parentControl != null) { int index = parentControl.ItemContainerGenerator.IndexFromContainer(item); if (index != parentControl.Items.Count - 1) // if this is not the last item { nextNodeAtSameLevel = parentControl.ItemContainerGenerator.ContainerFromIndex(index + 1) as MultiSelectTreeViewItem; } } return nextNodeAtSameLevel; }
/// <summary> /// Retrieve the last displayed child node of the given one. /// </summary> /// <param name="item">The node starting with you want to retrieve the last visible node.</param> /// <returns>The last child node that is displayed, or the node itself in case it is not expanded.</returns> public static MultiSelectTreeViewItem GetLastVisibleChildNodeOf(MultiSelectTreeViewItem item) { MultiSelectTreeViewItem lastVisibleNode = item; // Retrieving last child of last expanded node while (lastVisibleNode != null && lastVisibleNode.Items.Count > 0 && lastVisibleNode.IsExpanded) lastVisibleNode = lastVisibleNode.ItemContainerGenerator.ContainerFromIndex(lastVisibleNode.Items.Count - 1) as MultiSelectTreeViewItem; return lastVisibleNode; }
private bool MoveDown(MultiSelectTreeView rootTreeView, Rect draggingRect, ref MultiSelectTreeViewItem draggingContainer, ref MultiSelectTreeViewItem lastOverlapContainer, ref DateTime startOverlapTime) { Size overlapSize = new Size(); Rect overlapItemRect = new Rect(); MultiSelectTreeViewItem overlapContainer = null; var sourceItemsControl = ItemsControl.ItemsControlFromItemContainer(draggingContainer); if (sourceItemsControl == null) { return(false); } var sourceCollection = sourceItemsControl.ItemsSource as IList <TestModel>; var sourceIndex = sourceItemsControl.ItemContainerGenerator.IndexFromContainer(draggingContainer); var sourceItem = sourceCollection[sourceIndex]; var sourcePos = draggingContainer.TranslatePoint(new Point(), rootTreeView); //从组中分离 if (IsFromGroup(sourceItemsControl) && sourceIndex == sourceItemsControl.Items.Count - 1 && DoubleUtil.GreaterThan(draggingRect.Y, sourcePos.Y + draggingContainer.ActualHeight / 2)) { //加入上层集合 var superItemsControl = ItemsControl.ItemsControlFromItemContainer(sourceItemsControl); var superCollection = superItemsControl.ItemsSource as IList <TestModel>; var superIndex = superItemsControl.ItemContainerGenerator.IndexFromContainer(sourceItemsControl); sourceCollection.RemoveAt(sourceIndex); if (superIndex + 1 < superItemsControl.Items.Count) { superCollection.Insert(superIndex + 1, sourceItem); draggingContainer = ContainerFromIndex(superItemsControl, superIndex + 1) as MultiSelectTreeViewItem; } else { superCollection.Add(sourceItem); draggingContainer = ContainerFromIndex(superItemsControl, superCollection.Count - 1) as MultiSelectTreeViewItem; } //原组若剩余一项,则将该项加入上层集合,移除组 if (sourceItemsControl.Items.Count == 1) { sourceItem = sourceCollection[0]; sourceCollection.RemoveAt(0); superCollection.Insert(superIndex + 1, sourceItem); superCollection.RemoveAt(superIndex); } lastOverlapContainer = null; return(true); } if (!FindFirstDownItemWithValidOverlap(rootTreeView, sourceItemsControl, sourceIndex + 1, draggingContainer, draggingRect, ref overlapSize, ref overlapItemRect, ref overlapContainer)) { return(false); } var targetItemsControl = ItemsControl.ItemsControlFromItemContainer(overlapContainer); var targetCollection = targetItemsControl.ItemsSource as IList <TestModel>; var targetIndex = targetItemsControl.ItemContainerGenerator.IndexFromContainer(overlapContainer); if (DoubleUtil.LessThan(draggingRect.Bottom, overlapItemRect.Y + overlapItemRect.Height / 2)) { //Do noting } else if (DoubleUtil.LessThan(draggingRect.Bottom, overlapItemRect.Y + overlapItemRect.Height * 3 / 4)) // 1/4 -> 3/4 height { //非同组,则加入 if (IsFromGroup(targetItemsControl) && targetItemsControl != sourceItemsControl) { sourceCollection.RemoveAt(sourceIndex); targetCollection.Insert(0, sourceItem); lastOverlapContainer = null; draggingContainer = ContainerFromIndex(targetItemsControl, 0) as MultiSelectTreeViewItem; } } else if (DoubleUtil.GreaterThan(draggingRect.Y, overlapItemRect.Y + overlapItemRect.Height / 4)) //Top -> 1/4 height 移动 { sourceCollection.RemoveAt(sourceIndex); targetCollection.Insert(targetIndex, sourceItem); lastOverlapContainer = null; draggingContainer = ContainerFromIndex(targetItemsControl, targetIndex) as MultiSelectTreeViewItem; } else //处理悬停,创建新组 { if (!DealHover( targetItemsControl, targetCollection, targetIndex, sourceCollection, sourceIndex, sourceItem, targetIndex - 1, overlapContainer, ref lastOverlapContainer, ref startOverlapTime)) { return(false); } } return(true); }
private bool FindFirstDownItemWithValidOverlap(MultiSelectTreeView rootTreeView, ItemsControl parentItemsControl, int startIndex, MultiSelectTreeViewItem draggingContainer, Rect draggingRect, ref Size overlapSize, ref Rect overlapContainerRect, ref MultiSelectTreeViewItem overlapContainer) { while (startIndex < parentItemsControl.Items.Count) { var downTreeViewItem = parentItemsControl.ItemContainerGenerator.ContainerFromIndex(startIndex++) as MultiSelectTreeViewItem; if (downTreeViewItem == null) { continue; } if (downTreeViewItem.HasItems && downTreeViewItem.IsExpanded //for move over the collapsed group //&& !(downTreeViewItem.DataContext as JOB_INFO).IsLocked //for IsLocked is false //&& draggingContainer.ContainDepth() + downTreeViewItem.InDepth() < LogicCenter.JobListMaxDepth //for tree depth && ItemsControl.ItemsControlFromItemContainer(draggingContainer) == parentItemsControl) //for move into first group { if (FindFirstDownItemWithValidOverlap(rootTreeView, downTreeViewItem, 0, draggingContainer, draggingRect, ref overlapSize, ref overlapContainerRect, ref overlapContainer)) { return(true); } } else { var downItemPos = downTreeViewItem.TranslatePoint(new Point(), rootTreeView); var downItemOverlapSize = GetOverlapSize(new Rect(downItemPos, new Point(downItemPos.X + downTreeViewItem.ActualWidth, downItemPos.Y + downTreeViewItem.ActualHeight)), draggingRect); if (downItemOverlapSize.IsEmpty || DoubleUtil.IsZero(downItemOverlapSize.Width) || DoubleUtil.IsZero(downItemOverlapSize.Height)) { continue; } overlapSize = downItemOverlapSize; overlapContainerRect = new Rect(downItemPos.X, downItemPos.Y, downTreeViewItem.ActualWidth, downTreeViewItem.ActualHeight); overlapContainer = downTreeViewItem; return(true); } } ; var superIC = ItemsControl.ItemsControlFromItemContainer(parentItemsControl); if (superIC == null) { return(false); } var topIndex = superIC.ItemContainerGenerator.IndexFromContainer(parentItemsControl); return(FindFirstDownItemWithValidOverlap(rootTreeView, superIC, topIndex + 1, draggingContainer, draggingRect, ref overlapSize, ref overlapContainerRect, ref overlapContainer)); }
private static ContentPresenter GetContentPresenter(MultiSelectTreeViewItem treeViewItem) { var contentPresenter = treeViewItem.Template.FindName("PART_Header", treeViewItem) as ContentPresenter; return(contentPresenter); }
public void Invoke() { MultiSelectTreeViewItem treeViewItem = (MultiSelectTreeViewItem)Owner; treeViewItem.InvokeMouseDown(); }
/// <summary> /// Initializes a new instance of the <see cref="MultiSelectTreeViewItemAutomationPeer"/> /// class. /// </summary> /// <param name="owner"> /// Das <see cref="T:System.Windows.Controls.MultiSelectTreeViewItem"/>, das diesem /// <see cref="T:System.Windows.Automation.Peers.MultiSelectTreeViewItemAutomationPeer"/> /// zugeordnet ist. /// </param> public MultiSelectTreeViewItemAutomationPeer(MultiSelectTreeViewItem owner) : base(owner) { }