Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Controls / TreeViewItem.cs / 1305600 / TreeViewItem.cs
//---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Specialized; using System.ComponentModel; using System.Diagnostics; using System.Windows; using System.Windows.Automation.Peers; using System.Windows.Controls.Primitives; using System.Windows.Input; using System.Windows.Media; using System.Windows.Threading; using MS.Internal; using MS.Internal.KnownBoxes; namespace System.Windows.Controls { ////// A child of a [TemplatePart(Name = "PART_Header", Type = typeof(FrameworkElement))] [StyleTypedProperty(Property = "ItemContainerStyle", StyleTargetType = typeof(TreeViewItem))] public class TreeViewItem : HeaderedItemsControl, VirtualizingStackPanel.IProvideStackingSize { #region Constructors static TreeViewItem() { DefaultStyleKeyProperty.OverrideMetadata(typeof(TreeViewItem), new FrameworkPropertyMetadata(typeof(TreeViewItem))); VirtualizingStackPanel.IsVirtualizingProperty.OverrideMetadata(typeof(TreeViewItem), new FrameworkPropertyMetadata(BooleanBoxes.FalseBox)); _dType = DependencyObjectType.FromSystemTypeInternal(typeof(TreeViewItem)); KeyboardNavigation.DirectionalNavigationProperty.OverrideMetadata(typeof(TreeViewItem), new FrameworkPropertyMetadata(KeyboardNavigationMode.Continue)); KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(TreeViewItem), new FrameworkPropertyMetadata(KeyboardNavigationMode.None)); IsTabStopProperty.OverrideMetadata(typeof(TreeViewItem), new FrameworkPropertyMetadata(BooleanBoxes.FalseBox)); IsMouseOverPropertyKey.OverrideMetadata(typeof(TreeViewItem), new UIPropertyMetadata(new PropertyChangedCallback(OnVisualStatePropertyChanged))); IsEnabledProperty.OverrideMetadata(typeof(TreeViewItem), new UIPropertyMetadata(new PropertyChangedCallback(OnVisualStatePropertyChanged))); Selector.IsSelectionActivePropertyKey.OverrideMetadata(typeof(TreeViewItem), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnVisualStatePropertyChanged))); EventManager.RegisterClassHandler(typeof(TreeViewItem), FrameworkElement.RequestBringIntoViewEvent, new RequestBringIntoViewEventHandler(OnRequestBringIntoView)); EventManager.RegisterClassHandler(typeof(TreeViewItem), Mouse.MouseDownEvent, new MouseButtonEventHandler(OnMouseButtonDown), true); } ///. /// /// Creates an instance of this control. /// public TreeViewItem() { } #endregion #region Public Properties ////// The DependencyProperty for the public static readonly DependencyProperty IsExpandedProperty = DependencyProperty.Register( "IsExpanded", typeof(bool), typeof(TreeViewItem), new FrameworkPropertyMetadata( BooleanBoxes.FalseBox, new PropertyChangedCallback(OnIsExpandedChanged))); ///property. /// Default Value: false /// /// Specifies whether this item has expanded its children or not. /// public bool IsExpanded { get { return (bool) GetValue(IsExpandedProperty); } set { SetValue(IsExpandedProperty, value); } } private bool CanExpand { get { return HasItems; } } private static void OnIsExpandedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TreeViewItem item = (TreeViewItem) d; bool isExpanded = (bool) e.NewValue; if (!isExpanded) { TreeView tv = item.ParentTreeView; if (tv != null) { tv.HandleSelectionAndCollapsed(item); } } TreeViewItemAutomationPeer peer = UIElementAutomationPeer.FromElement(item) as TreeViewItemAutomationPeer; if (peer != null) { peer.RaiseExpandCollapseAutomationEvent((bool)e.OldValue, isExpanded); } if (isExpanded) { item.OnExpanded(new RoutedEventArgs(ExpandedEvent, item)); } else { item.OnCollapsed(new RoutedEventArgs(CollapsedEvent, item)); } item.UpdateVisualState(); } ////// The DependencyProperty for the public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register( "IsSelected", typeof(bool), typeof(TreeViewItem), new FrameworkPropertyMetadata( BooleanBoxes.FalseBox, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnIsSelectedChanged))); ///property. /// Default Value: false /// /// Specifies whether this item is selected or not. /// public bool IsSelected { get { return (bool) GetValue(IsSelectedProperty); } set { SetValue(IsSelectedProperty, value); } } private static void OnIsSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TreeViewItem item = (TreeViewItem)d; bool isSelected = (bool) e.NewValue; item.Select(isSelected); TreeViewItemAutomationPeer peer = UIElementAutomationPeer.FromElement(item) as TreeViewItemAutomationPeer; if (peer != null) { peer.RaiseAutomationIsSelectedChanged(isSelected); } if (isSelected) { item.OnSelected(new RoutedEventArgs(SelectedEvent, item)); } else { item.OnUnselected(new RoutedEventArgs(UnselectedEvent, item)); } item.UpdateVisualState(); } ////// DependencyProperty for public static readonly DependencyProperty IsSelectionActiveProperty = Selector.IsSelectionActiveProperty.AddOwner(typeof(TreeViewItem)); ///. /// /// Indicates whether the keyboard focus is within the TreeView. /// When keyboard focus moves to a Menu or Toolbar, then the selection remains active. /// Use this property to style the TreeViewItem to look different when focus is not within the TreeView. /// [Browsable(false), Category("Appearance"), ReadOnly(true)] public bool IsSelectionActive { get { return (bool)GetValue(IsSelectionActiveProperty); } } #endregion #region Public Events ////// Event fired when public static readonly RoutedEvent ExpandedEvent = EventManager.RegisterRoutedEvent("Expanded", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TreeViewItem)); ///becomes true. /// /// Event fired when [Category("Behavior")] public event RoutedEventHandler Expanded { add { AddHandler(ExpandedEvent, value); } remove { RemoveHandler(ExpandedEvent, value); } } ///becomes true. /// /// Called when /// Event arguments. protected virtual void OnExpanded(RoutedEventArgs e) { RaiseEvent(e); } ///becomes true. /// Default implementation fires the event. /// /// Event fired when public static readonly RoutedEvent CollapsedEvent = EventManager.RegisterRoutedEvent("Collapsed", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TreeViewItem)); ///becomes false. /// /// Event fired when [Category("Behavior")] public event RoutedEventHandler Collapsed { add { AddHandler(CollapsedEvent, value); } remove { RemoveHandler(CollapsedEvent, value); } } ///becomes false. /// /// Called when /// Event arguments. protected virtual void OnCollapsed(RoutedEventArgs e) { RaiseEvent(e); } ///becomes false. /// Default implementation fires the event. /// /// Event fired when public static readonly RoutedEvent SelectedEvent = EventManager.RegisterRoutedEvent("Selected", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TreeViewItem)); ///becomes true. /// /// Event fired when [Category("Behavior")] public event RoutedEventHandler Selected { add { AddHandler(SelectedEvent, value); } remove { RemoveHandler(SelectedEvent, value); } } ///becomes true. /// /// Called when /// Event arguments. protected virtual void OnSelected(RoutedEventArgs e) { RaiseEvent(e); } ///becomes true. /// Default implementation fires the event. /// /// Event fired when public static readonly RoutedEvent UnselectedEvent = EventManager.RegisterRoutedEvent("Unselected", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TreeViewItem)); ///becomes false. /// /// Event fired when [Category("Behavior")] public event RoutedEventHandler Unselected { add { AddHandler(UnselectedEvent, value); } remove { RemoveHandler(UnselectedEvent, value); } } ///becomes false. /// /// Called when /// Event arguments. protected virtual void OnUnselected(RoutedEventArgs e) { RaiseEvent(e); } #endregion #region Public Methods ///becomes false. /// Default implementation fires the event. /// /// Expands this TreeViewItem and all of the TreeViewItems inside its subtree. /// public void ExpandSubtree() { ExpandRecursive(this); } #endregion #region Internal Methods ////// TreeView keeps track of the size estimate; forward the call to it. /// ///double VirtualizingStackPanel.IProvideStackingSize.EstimatedContainerSize(bool isHorizontal) { TreeView parent = ParentTreeView; Size estimate = Size.Empty; if (parent != null) { estimate = ParentTreeView.CurrentContainerSizeEstimate; } return isHorizontal ? estimate.Width : estimate.Height; } /// /// Return the size of the header in the requested direction. /// /// ///double VirtualizingStackPanel.IProvideStackingSize.HeaderSize(bool isHorizontal) { UIElement header = null; ControlTemplate template = Template; if (template != null) { header = template.FindName("PART_Header", this) as UIElement; if (header != null) { return isHorizontal ? header.DesiredSize.Width : header.DesiredSize.Height; } } return 0d; } #endregion #region Implementation #region Tree /// /// Walks up the parent chain of TreeViewItems to the top TreeView. /// internal TreeView ParentTreeView { get { ItemsControl parent = ParentItemsControl; while (parent != null) { TreeView tv = parent as TreeView; if (tv != null) { return tv; } parent = ItemsControl.ItemsControlFromItemContainer(parent); } return null; } } ////// Returns the immediate parent TreeViewItem. Null if the parent is a TreeView. /// internal TreeViewItem ParentTreeViewItem { get { return ParentItemsControl as TreeViewItem; } } ////// Returns the immediate parent ItemsControl. /// internal ItemsControl ParentItemsControl { get { return ItemsControl.ItemsControlFromItemContainer(this); } } #endregion #region Selection ////// Called when the visual parent of this element changes. /// /// protected internal override void OnVisualParentChanged(DependencyObject oldParent) { // When TreeViewItem is added to the visual tree we check if IsSelected is set to true // In this case we need to update the tree selection if (VisualTreeHelper.GetParent(this) != null) { if (IsSelected) { Select(true); } } base.OnVisualParentChanged(oldParent); } private void Select(bool selected) { TreeView tree = ParentTreeView; ItemsControl parent = ParentItemsControl; if ((tree != null) && (parent != null) && !tree.IsSelectionChangeActive) { // Give the TreeView a reference to this container and its data object data = parent.GetItemOrContainerFromContainer(this); tree.ChangeSelection(data, this, selected); // Making focus of TreeViewItem synchronize with selection if needed. if (selected && tree.IsKeyboardFocusWithin && !IsKeyboardFocusWithin) { Focus(); } } } private bool ContainsSelection { get { return ReadControlFlag(ControlBoolFlags.ContainsSelection); } set { WriteControlFlag(ControlBoolFlags.ContainsSelection, value); } } internal void UpdateContainsSelection(bool selected) { TreeViewItem parent = ParentTreeViewItem; while (parent != null) { parent.ContainsSelection = selected; parent = parent.ParentTreeViewItem; } } #endregion #region Input ////// This method is invoked when the IsFocused property changes to true. /// /// Event arguments. protected override void OnGotFocus(RoutedEventArgs e) { Select(true); base.OnGotFocus(e); } ////// Called when the left mouse button is pressed down. /// /// Event arguments protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) { if (!e.Handled && IsEnabled) { if (Focus()) { e.Handled = true; } if ((e.ClickCount % 2) == 0) { SetCurrentValueInternal(IsExpandedProperty, BooleanBoxes.Box(!IsExpanded)); e.Handled = true; } } base.OnMouseLeftButtonDown(e); } ////// Called when a keyboard key is pressed down. /// /// Event Arguments protected override void OnKeyDown(KeyEventArgs e) { base.OnKeyDown(e); if (!e.Handled) { switch (e.Key) { case Key.Add: if (CanExpandOnInput && !IsExpanded) { SetCurrentValueInternal(IsExpandedProperty, BooleanBoxes.TrueBox); e.Handled = true; } break; case Key.Subtract: if (CanExpandOnInput && IsExpanded) { SetCurrentValueInternal(IsExpandedProperty, BooleanBoxes.FalseBox); e.Handled = true; } break; case Key.Left: case Key.Right: if (LogicalLeft(e.Key)) { if (!IsControlKeyDown && CanExpandOnInput && IsExpanded) { if (IsFocused) { SetCurrentValueInternal(IsExpandedProperty, BooleanBoxes.FalseBox); } else { Focus(); } e.Handled = true; } } else { if (!IsControlKeyDown && CanExpandOnInput) { if (!IsExpanded) { SetCurrentValueInternal(IsExpandedProperty, BooleanBoxes.TrueBox); e.Handled = true; } else if (HandleDownKey()) { e.Handled = true; } } } break; case Key.Down: if (!IsControlKeyDown && HandleDownKey()) { e.Handled = true; } break; case Key.Up: if (!IsControlKeyDown && HandleUpKey()) { e.Handled = true; } break; } } } private bool LogicalLeft(Key key) { bool invert = (FlowDirection == FlowDirection.RightToLeft); return (!invert && (key == Key.Left)) || (invert && (key == Key.Right)); } private static bool IsControlKeyDown { get { return ((Keyboard.Modifiers & ModifierKeys.Control) == (ModifierKeys.Control)); } } private bool CanExpandOnInput { get { return CanExpand && IsEnabled; } } internal bool HandleUpKey() { if (AllowHandleKeyEvent(FocusNavigationDirection.Up)) { ItemsControl item = FindPreviousFocusableItem(); if (item != null) { if (item == ParentItemsControl && item == ParentTreeView) { return true; // Prevents KeyboardNavigation from focusing one of our children } return item.Focus(); } } return false; // Not handled } internal bool HandleDownKey() { if (AllowHandleKeyEvent(FocusNavigationDirection.Down)) { return FocusDown(); } return false; // Not handled } private bool AllowHandleKeyEvent(FocusNavigationDirection direction) { if (!IsSelected) { return false; } DependencyObject currentFocus = Keyboard.FocusedElement as DependencyObject; if (currentFocus != null && UIElementHelper.IsUIElementOrUIElement3D(currentFocus)) { DependencyObject predict = UIElementHelper.PredictFocus(currentFocus, direction); if (predict != currentFocus) { while (predict != null) { TreeViewItem item = predict as TreeViewItem; if (item == this) { return false; // There is a focusable item in the header } else if ((item != null) || (predict is TreeView)) { return true; } predict = VisualTreeHelper.GetParent(predict); } } } return true; } internal static bool FocusIntoItem(TreeViewItem item) { Debug.Assert(item.IsEnabled, "Only call FocusIntoItem with an enabled item"); TreeViewItem lastItem = FindLastFocusableItem(item); if (lastItem != null) { return lastItem.Focus(); } return false; } internal bool FocusDown() { TreeViewItem item = FindNextFocusableItem(true); if (item != null) { return item.Focus(); } return false; } ////// Returns the next item in the TreeView hierarchy, regardless of depth. /// ///private TreeViewItem FindNextFocusableItem(bool walkIntoSubtree) { // // First walk into this item's subtree // if (walkIntoSubtree && IsExpanded && CanExpand) { TreeViewItem item = ItemContainerGenerator.ContainerFromIndex(0) as TreeViewItem; if (item != null) { if (item.IsEnabled) { return item; } else { return item.FindNextFocusableItem(false); } } } // // Otherwise go to the next sibling // ItemsControl parent = ParentItemsControl; if (parent != null) { TreeViewItem item; int index = parent.ItemContainerGenerator.IndexFromContainer(this); int count = parent.Items.Count; while (index < count) { // Find the next sibling index++; item = parent.ItemContainerGenerator.ContainerFromIndex(index) as TreeViewItem; if ((item != null) && item.IsEnabled) { return item; } } // This item has no next sibling, find the parent's next sibling item = parent as TreeViewItem; if (item != null) { return item.FindNextFocusableItem(false); } } return null; // Not handled } /// /// Returns the previous item in the TreeView hierarchy, regardless of depth. /// ///private ItemsControl FindPreviousFocusableItem() { ItemsControl parent = ParentItemsControl; if (parent != null) { int index = parent.ItemContainerGenerator.IndexFromContainer(this); while (index > 0) { index--; TreeViewItem item = parent.ItemContainerGenerator.ContainerFromIndex(index) as TreeViewItem; if ((item != null) && item.IsEnabled) { TreeViewItem lastItem = FindLastFocusableItem(item); if (lastItem != null) { return lastItem; } } } return parent; } return null; } /// /// Returns the last focusable item in the given subtree. /// ///private static TreeViewItem FindLastFocusableItem(TreeViewItem item) { Debug.Assert(item.IsEnabled, "Only call FocusIntoItem with an enabled item"); TreeViewItem lastItem = null; // Find the last child in the subtree. int index = -1; TreeViewItem parent = null; while (item != null) { if (item.IsEnabled) { if (!item.IsExpanded || !item.CanExpand) { return item; } lastItem = item; parent = item; index = item.Items.Count - 1; } else if (index > 0) { index--; } else { break; } item = parent.ItemContainerGenerator.ContainerFromIndex(index) as TreeViewItem; } if (lastItem != null) { return lastItem; } return null; } /// /// This should be PredictFocus but since UIElement.PredictFocus is sealed by FE we can't override it. /// TreeViewItem has its own code for deciding where focus should go. /// /// ///internal DependencyObject InternalPredictFocus(FocusNavigationDirection direction) { switch (direction) { case FocusNavigationDirection.Left: case FocusNavigationDirection.Up: return FindPreviousFocusableItem(); case FocusNavigationDirection.Right: case FocusNavigationDirection.Down: return FindNextFocusableItem(true); default: return null; } } private static void OnMouseButtonDown(object sender, MouseButtonEventArgs e) { TreeViewItem tvi = (TreeViewItem)sender; TreeView tv = tvi.ParentTreeView; if (tv != null) { tv.HandleMouseButtonDown(); } } private static void OnRequestBringIntoView(object sender, RequestBringIntoViewEventArgs e) { if (e.TargetObject == sender) { ((TreeViewItem)sender).HandleBringIntoView(e); } } private void HandleBringIntoView(RequestBringIntoViewEventArgs e) { TreeViewItem parent = ParentTreeViewItem; while (parent != null) { if (!parent.IsExpanded) { parent.SetCurrentValueInternal(IsExpandedProperty, BooleanBoxes.TrueBox); } parent = parent.ParentTreeViewItem; } // See FrameworkElement.BringIntoView() comments //dmitryt, bug 1126518. On new/updated elements RenderSize isn't yet computed //so we need to postpone the rect computation until layout is done. //this is accomplished by passing Empty rect here and then asking for RenderSize //in IScrollInfo when it actually executes an async MakeVisible command. if (e.TargetRect.IsEmpty) { FrameworkElement header = HeaderElement; if (header != null) { e.Handled = true; header.BringIntoView(); } else { // Header is not generated yet. Could happen if BringIntoView is called on container before layout. Try later. Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new DispatcherOperationCallback(BringItemIntoView), null); } } } private object BringItemIntoView(object args) { FrameworkElement header = HeaderElement; if (header != null) { header.BringIntoView(); } return null; } private FrameworkElement HeaderElement { get { return GetTemplateChild(HeaderPartName) as FrameworkElement; } } internal bool HandleScrollByPage(bool up, ScrollViewer scroller, double viewportHeight, double startTop, double startBottom, out double currentDelta) { double closeEdge; currentDelta = CalculateDelta(up, this, scroller, startTop, startBottom, out closeEdge); if (DoubleUtil.GreaterThan(closeEdge, viewportHeight)) { // The item does not fit in view at all return false; // Did not focus } else if (DoubleUtil.LessThanOrClose(currentDelta, viewportHeight)) { // This item and all its children fit in view. // There may be others that also fit in view, so don't focus now return false; // Did not focus } else { // This item is partially in view // Test if the header element is in view bool headerInView = false; FrameworkElement header = HeaderElement; if (header != null) { double delta = CalculateDelta(up, header, scroller, startTop, startBottom); if (DoubleUtil.LessThanOrClose(delta, viewportHeight)) { // The header is in view headerInView = true; } } TreeViewItem select = null; int count = Items.Count; bool skip = up && ContainsSelection; for (int index = (up ? count - 1 : 0); (0 <= index) && (index < count); index = index + (up ? -1 : 1)) { TreeViewItem item = ItemContainerGenerator.ContainerFromIndex(index) as TreeViewItem; if ((item != null) && item.IsEnabled) { if (skip) { if (item.IsSelected) { skip = false; continue; // Go to the next one } else if (item.ContainsSelection) { skip = false; // Look inside this one } else { continue; } } double delta; if (item.HandleScrollByPage(up, scroller, viewportHeight, startTop, startBottom, out delta)) { // This item or one of its children was focused return true; } else if (DoubleUtil.GreaterThan(delta, viewportHeight)) { // This item does not fit break; } else { // This item does fit, but we should continue searching select = item; } } } if (select != null) { // Earlier we found an item that fit but didn't focus it at that time if (up) { return select.Focus(); } else { return FocusIntoItem(select); } } else if (headerInView) { // None of the children could be focused, the header is in view even though // the whole subtree isn't in view. There shouldn't be any more focusable // items that fit, so select this one. return Focus(); } } return false; // Did not focus } private static double CalculateDelta(bool up, FrameworkElement item, ScrollViewer scroller, double startTop, double startBottom) { double closeEdge; return CalculateDelta(up, item, scroller, startTop, startBottom, out closeEdge); } private static double CalculateDelta(bool up, FrameworkElement item, ScrollViewer scroller, double startTop, double startBottom, out double closeEdge) { double top, bottom; GetTopAndBottom(item, scroller, out top, out bottom); if (up) { closeEdge = startBottom - bottom; return startBottom - top; } else { closeEdge = top - startTop; return bottom - startTop; } } internal void GetTopAndBottom(Visual parent, out double top, out double bottom) { FrameworkElement header = HeaderElement; if (header != null) { GetTopAndBottom(header, parent, out top, out bottom); } else { GetTopAndBottom(this, parent, out top, out bottom); } } private static void GetTopAndBottom(FrameworkElement item, Visual parent, out double top, out double bottom) { GeneralTransform transform = item.TransformToAncestor(parent); Point upperLeft; if (transform.TryTransform(new Point(0.0, 0.0), out upperLeft)) { top = upperLeft.Y; } else { top = 0.0; } Point lowerLeft; if (transform.TryTransform(new Point(0.0, item.RenderSize.Height), out lowerLeft)) { bottom = lowerLeft.Y; } else { bottom = top + item.RenderSize.Height; } } #endregion #region Containers /// /// Returns true if the item is or should be its own container. /// /// The item to test. ///true if its type matches the container type. protected override bool IsItemItsOwnContainerOverride(object item) { return item is TreeViewItem; } ////// Create or identify the element used to display the given item. /// ///The container. protected override DependencyObject GetContainerForItemOverride() { return new TreeViewItem(); } ////// We only override this to help with container estimation for virtualization /// /// ///protected override Size MeasureOverride(Size constraint) { Size desiredSize = base.MeasureOverride(constraint); if (IsVirtualizing && !IsExpanded && IsVisible) { TreeView parent = ParentTreeView; if (parent != null) { parent.RegisterContainerSize(IsLogicalHorizontal ? desiredSize.Width : desiredSize.Height); } } return desiredSize; } /// /// Send down the IsVirtualizing property if it's set on this element. /// /// /// protected override void PrepareContainerForItemOverride(DependencyObject element, object item) { base.PrepareContainerForItemOverride(element, item); IsVirtualizingPropagationHelper(this, element); } // Synchronizes the value of the child's IsVirtualizing property with that of the parent's internal static void IsVirtualizingPropagationHelper(DependencyObject parent, DependencyObject element) { SynchronizeValue(VirtualizingStackPanel.IsVirtualizingProperty, parent, element); SynchronizeValue(VirtualizingStackPanel.VirtualizationModeProperty, parent, element); } private static void SynchronizeValue(DependencyProperty dp, DependencyObject parent, DependencyObject child) { if (IsDefaultValue(dp, parent)) { child.ClearValue(dp); } else { object value = parent.GetValue(dp); child.SetValue(dp, value); } } private static bool IsDefaultValue(DependencyProperty dp, DependencyObject element) { bool hasModifiers; return element.GetValueSource(dp, null, out hasModifiers) == BaseValueSourceInternal.Default; } ////// This method is invoked when the Items property changes. /// protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e) { switch (e.Action) { case NotifyCollectionChangedAction.Remove: case NotifyCollectionChangedAction.Reset: if (ContainsSelection) { TreeView tree = ParentTreeView; if ((tree != null) && !tree.IsSelectedContainerHookedUp) { ContainsSelection = false; Select(true); } } break; case NotifyCollectionChangedAction.Replace: if (ContainsSelection) { TreeView tree = ParentTreeView; if (tree != null) { // When Selected item is replaced - remove the selection // Revisit the condition when we support duplicate items in Items collection: if e.OldItems[0] is the same as selected items we will unselect the selected item object selectedItem = tree.SelectedItem; if ((selectedItem != null) && selectedItem.Equals(e.OldItems[0])) { tree.ChangeSelection(selectedItem, tree.SelectedContainer, false); } } } break; case NotifyCollectionChangedAction.Add: case NotifyCollectionChangedAction.Move: break; default: throw new NotSupportedException(SR.Get(SRID.UnexpectedCollectionChangeAction, e.Action)); } } ////// Recursively & syncronously expand all the nodes in this subtree. /// private static void ExpandRecursive(TreeViewItem item) { if (item == null) { return; } // Expand the current item if (!item.IsExpanded) { item.SetCurrentValueInternal(IsExpandedProperty, BooleanBoxes.TrueBox); } // ApplyTemplate in order to generate the ItemsPresenter and the ItemsPanel. Note that in the // virtualizing case even if the item is marked expanded we still need to do this step in order to // regenerate the visuals because they may have been virtualized away. item.ApplyTemplate(); ItemsPresenter itemsPresenter = (ItemsPresenter)item.Template.FindName("ItemsHost", item); if (itemsPresenter != null) { itemsPresenter.ApplyTemplate(); } else { item.UpdateLayout(); } VirtualizingPanel virtualizingPanel = item.ItemsHost as VirtualizingPanel; item.ItemsHost.EnsureGenerator(); for (int i = 0, count = item.Items.Count; i < count; i++) { TreeViewItem subitem; if (virtualizingPanel != null) { // We need to bring the item into view so that the container will be generated. virtualizingPanel.BringIndexIntoView(i); subitem = (TreeViewItem)item.ItemContainerGenerator.ContainerFromIndex(i); } else { subitem = (TreeViewItem)item.ItemContainerGenerator.ContainerFromIndex(i); // We dont actually need to bring this into view, but we'll do it // anyways to maintain the same behavior as with a virtualizing panel. subitem.BringIntoView(); } if (subitem != null) { ExpandRecursive(subitem); } } } #endregion #region Automation ////// Creates AutomationPeer ( protected override AutomationPeer OnCreateAutomationPeer() { return new TreeViewItemAutomationPeer(this); } #endregion Automation #region DTypeThemeStyleKey // Returns the DependencyObjectType for the registered ThemeStyleKey's default // value. Controls will override this method to return approriate types. internal override DependencyObjectType DTypeThemeStyleKey { get { return _dType; } } private static DependencyObjectType _dType; #endregion DTypeThemeStyleKey #endregion #region Visual States internal override void ChangeVisualState(bool useTransitions) { // Handle the Common states if (!IsEnabled) { VisualStates.GoToState(this, useTransitions, VisualStates.StateDisabled, VisualStates.StateNormal); } else if (IsMouseOver) { VisualStates.GoToState(this, useTransitions, VisualStates.StateMouseOver, VisualStates.StateNormal); } else { VisualStates.GoToState(this, useTransitions, VisualStates.StateNormal); } // Handle the Focused states if (IsKeyboardFocused) { VisualStates.GoToState(this, useTransitions, VisualStates.StateFocused, VisualStates.StateUnfocused); } else { VisualStates.GoToState(this, useTransitions, VisualStates.StateUnfocused); } // Handle the Expansion states if (IsExpanded) { VisualStates.GoToState(this, useTransitions, VisualStates.StateExpanded); } else { VisualStates.GoToState(this, useTransitions, VisualStates.StateCollapsed); } // Handle the HasItems states if (HasItems) { VisualStates.GoToState(this, useTransitions, VisualStates.StateHasItems); } else { VisualStates.GoToState(this, useTransitions, VisualStates.StateNoItems); } // Handle the Selected states if (IsSelected) { if (IsSelectionActive) { VisualStates.GoToState(this, useTransitions, VisualStates.StateSelected); } else { VisualStates.GoToState(this, useTransitions, VisualStates.StateSelectedInactive, VisualStates.StateSelected); } } else { VisualStates.GoToState(this, useTransitions, VisualStates.StateUnselected); } base.ChangeVisualState(useTransitions); } #endregion #region Data private const string HeaderPartName = "PART_Header"; #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.) ///
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- CqlBlock.cs
- CorrelationQueryBehavior.cs
- ResourcePermissionBaseEntry.cs
- safesecurityhelperavalon.cs
- FlowDocument.cs
- ToolTip.cs
- dbenumerator.cs
- Switch.cs
- Msec.cs
- SystemIPInterfaceProperties.cs
- XmlBoundElement.cs
- CalendarKeyboardHelper.cs
- ModelVisual3D.cs
- DomainUpDown.cs
- ExtendedPropertyDescriptor.cs
- MethodBody.cs
- KeyTimeConverter.cs
- _Semaphore.cs
- SQlBooleanStorage.cs
- MailAddressCollection.cs
- DbTransaction.cs
- SafeRightsManagementQueryHandle.cs
- CodeExpressionCollection.cs
- StreamSecurityUpgradeInitiator.cs
- NodeLabelEditEvent.cs
- InternalConfigEventArgs.cs
- HtmlShim.cs
- Thread.cs
- ProfileGroupSettings.cs
- ClientUtils.cs
- FilterQueryOptionExpression.cs
- Button.cs
- MaskedTextBox.cs
- PerformanceCountersBase.cs
- DataBindingExpressionBuilder.cs
- DetailsViewModeEventArgs.cs
- EndpointAddressElementBase.cs
- ThaiBuddhistCalendar.cs
- SafeProcessHandle.cs
- Graph.cs
- ScrollBar.cs
- WebServiceParameterData.cs
- RotationValidation.cs
- WeakReadOnlyCollection.cs
- cookiecollection.cs
- SchemaComplexType.cs
- ControlBuilderAttribute.cs
- CompilerError.cs
- PointConverter.cs
- CursorInteropHelper.cs
- SerialPinChanges.cs
- TraceLevelStore.cs
- InvalidEnumArgumentException.cs
- MDIControlStrip.cs
- Block.cs
- TemplateField.cs
- GeneratedContractType.cs
- Assembly.cs
- OdbcEnvironmentHandle.cs
- CollectionChange.cs
- GuidelineCollection.cs
- HttpRawResponse.cs
- DebugViewWriter.cs
- ThicknessConverter.cs
- BuildManagerHost.cs
- LowerCaseStringConverter.cs
- MissingFieldException.cs
- ClientRolePrincipal.cs
- SystemIPv4InterfaceProperties.cs
- ListViewItemEventArgs.cs
- Border.cs
- PropertyGridDesigner.cs
- ListView.cs
- ListBoxChrome.cs
- IncrementalHitTester.cs
- GCHandleCookieTable.cs
- _HelperAsyncResults.cs
- ColorConvertedBitmap.cs
- DataReceivedEventArgs.cs
- InstanceValue.cs
- WebPartEditorCancelVerb.cs
- RubberbandSelector.cs
- ResourcePool.cs
- TableLayoutSettingsTypeConverter.cs
- TemplateControlBuildProvider.cs
- TextEffectCollection.cs
- Panel.cs
- KeyPressEvent.cs
- HttpInputStream.cs
- ProvidersHelper.cs
- Base64Encoder.cs
- UrlMappingsSection.cs
- TypeGeneratedEventArgs.cs
- XmlNotation.cs
- sqlstateclientmanager.cs
- SchemaNames.cs
- RestClientProxyHandler.cs
- WebPartUtil.cs
- HorizontalAlignConverter.cs
- NavigationProperty.cs