/// <summary> /// Creates the monitor with the tree to be processed. /// </summary> /// <param name="tree">The tree that renders the monitored /// items.</param> /// <exception cref="ArgumentNullException">If <paramref name="tree"/> /// is a null reference.</exception> public ItemMonitor(TreeViewBase <T> tree) { if (tree == null) { throw new ArgumentNullException("tree"); } this.tree = tree; }
/// <summary> /// A static event listener which is invoked if a tree's node is being /// expanded. This event is being observed because nodes may need to /// be created if lazy loading is active. /// </summary> /// <param name="sender">The processed <see cref="TreeViewBase{T}"/> /// control.</param> /// <param name="e">Event arguments. The <see cref="RoutedEventArgs.OriginalSource"/> /// property provides the expanded tree node.</param> private static void OnTreeNodeExpanded(object sender, RoutedEventArgs e) { TreeViewBase <T> owner = (TreeViewBase <T>)sender; TreeViewItem treeNode = (TreeViewItem)e.OriginalSource; owner.OnNodeExpanded(treeNode); //do NOT mark as handled - the event may bubble up the tree: //e.Handled = true; }
/// <summary> /// A static callback listener which is being invoked if the /// <see cref="AutoCollapseProperty"/> dependency property has /// been changed. Invokes the <see cref="OnAutoCollapsePropertyChanged"/> /// instance method of the changed instance. /// </summary> /// <param name="d">The currently processed owner of the property.</param> /// <param name="e">Provides information about the updated property.</param> private static void AutoCollapsePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TreeViewBase <T> owner = (TreeViewBase <T>)d; //don't do anything if the control is being created if (owner.IsInitialized) { owner.OnAutoCollapsePropertyChanged(e); } }
/// <summary> /// Handles changes on the <see cref="TreeStyleProperty"/> dependency property. As /// WPF internally uses the dependency property system and bypasses the /// <see cref="TreeStyle"/> property wrapper, updates should be handled here. /// </summary> /// <param name="d">The currently processed owner of the property.</param> /// <param name="e">Provides information about the updated property.</param> private static void TreeStylePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TreeViewBase <T> owner = (TreeViewBase <T>)d; Style newValue = (Style)e.NewValue; //assign new style if (owner.Tree != null && newValue != null) { owner.Tree.Style = newValue; } }
/// <summary> /// Handles changes on the <see cref="ItemsProperty"/> dependency property. As /// WPF internally uses the dependency property system and bypasses the /// <see cref="Items"/> property wrapper, updates should be handled here. /// </summary> /// <param name="d">The currently processed owner of the property.</param> /// <param name="e">Provides information about the updated property.</param> private static void ItemsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TreeViewBase <T> owner = (TreeViewBase <T>)d; IEnumerable <T> oldValue = (IEnumerable <T>)e.OldValue; IEnumerable <T> newValue = (IEnumerable <T>)e.NewValue; //don't do anything if the control is being created if (owner.IsInitialized) { owner.OnItemsPropertyChanged(oldValue, newValue); } }
/// <summary> /// Handles changes on the <see cref="ObserveChildItemsProperty"/> dependency property. As /// WPF internally uses the dependency property system and bypasses the /// <see cref="ObserveChildItems"/> property wrapper, updates should be handled here. /// </summary> /// <param name="d">The currently processed owner of the property.</param> /// <param name="e">Provides information about the updated property.</param> private static void ObserveChildItemsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { //don't do anything if the control is being created TreeViewBase <T> owner = (TreeViewBase <T>)d; if (!owner.IsInitialized) { return; } //recreate the three owner.Refresh(owner.GetTreeLayout()); }
/// <summary> /// Handles changes on the <see cref="TreeNodeStyleProperty"/> dependency property. As /// WPF internally uses the dependency property system and bypasses the /// <see cref="TreeNodeStyle"/> property wrapper, updates should be handled here. /// </summary> /// <param name="d">The currently processed owner of the property.</param> /// <param name="e">Provides information about the updated property.</param> private static void TreeNodeStylePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { //don't do anything if the control is being created TreeViewBase <T> owner = (TreeViewBase <T>)d; if (!owner.IsInitialized || owner.Tree == null) { return; } //assign the style to every node of the tree foreach (TreeViewItem node in owner.RecursiveNodeList) { owner.ApplyNodeStyle(node, (T)node.Header); } }
/// <summary> /// Handles changes on the <see cref="RootNodeProperty"/> dependency property. As /// WPF internally uses the dependency property system and bypasses the /// <see cref="RootNode"/> property wrapper, updates should be handled here. /// </summary> /// <param name="d">The currently processed owner of the property.</param> /// <param name="e">Provides information about the updated property.</param> private static void RootNodePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { //just recreate the tree - this takes care of everything TreeViewBase <T> owner = (TreeViewBase <T>)d; TreeViewItem newValue = (TreeViewItem)e.NewValue; //don't do anything if the control is being created if (!owner.IsInitialized) { return; } owner.Refresh(owner.GetTreeLayout()); //apply sorting on root or tree (if the new value is null) owner.ApplySorting(newValue, null); }
/// <summary> /// Handles changes on the <see cref="NodeSortDescriptionsProperty"/> dependency property. As /// WPF internally uses the dependency property system and bypasses the /// <see cref="NodeSortDescriptions"/> property wrapper, updates should be handled here. /// </summary> /// <param name="d">The currently processed owner of the property.</param> /// <param name="e">Provides information about the updated property.</param> private static void NodeSortDescriptionsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { //don't do anything if the control is being created TreeViewBase <T> owner = (TreeViewBase <T>)d; if (!owner.IsInitialized || owner.Tree == null) { return; } //set sort parameters on tree (root == null) or root node owner.ApplySorting(owner.RootNode, null); //iterate over all nodes and apply sorting foreach (TreeViewItem item in owner.RecursiveNodeList) { owner.ApplySorting(item, (T)item.Header); } }
/// <summary> /// Handles changes on the <see cref="SelectedItemProperty"/> dependency property. As /// WPF internally uses the dependency property system and bypasses the /// <see cref="SelectedItem"/> property wrapper, updates should be handled here. /// </summary> /// <param name="d">The currently processed owner of the property.</param> /// <param name="e">Provides information about the updated property.</param> private static void SelectedItemPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TreeViewBase <T> owner = (TreeViewBase <T>)d; T newValue = (T)e.NewValue; T oldValue = (T)e.OldValue; TreeView tree = owner.Tree; //don't do anything if the control is being created or does //not have a tree attached if (!owner.IsInitialized || tree == null) { return; } //if the root node is collapsed, expand it if (owner.RootNode != null) { owner.RootNode.IsExpanded = true; } owner.OnSelectedItemPropertyChanged(newValue, oldValue); }
/// <summary> /// Handles changes on the <see cref="TreeProperty"/> dependency property. As /// WPF internally uses the dependency property system and bypasses the /// <see cref="TreeView"/> property wrapper, updates should be handled here. /// </summary> /// <param name="d">The currently processed owner of the property.</param> /// <param name="e">Provides information about the updated property.</param> private static void TreePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TreeViewBase <T> owner = (TreeViewBase <T>)d; TreeView oldValue = (TreeView)e.OldValue; TreeView newValue = (TreeView)e.NewValue; if (oldValue != null) { //deregister event listeners oldValue.SelectedItemChanged -= owner.OnSelectedItemChanged; oldValue.MouseRightButtonUp -= owner.OnRightMouseButtonUp; } //set the tree as the control content owner.Content = newValue; //only assign a style if it's not null if (newValue != null && owner.TreeStyle != null) { newValue.Style = owner.TreeStyle; } if (newValue != null) { //register event listeners newValue.SelectedItemChanged += owner.OnSelectedItemChanged; newValue.MouseRightButtonUp += owner.OnRightMouseButtonUp; } //don't do anything if the control is being created if (!owner.IsInitialized) { return; } //render the tree owner.Refresh(); }