Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / System / Windows / Controls / TreeViewItem.cs / 3 / 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 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 { #region Constructors static TreeViewItem() { DefaultStyleKeyProperty.OverrideMetadata(typeof(TreeViewItem), new FrameworkPropertyMetadata(typeof(TreeViewItem))); _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)); 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)); } } ////// 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)); } } ////// 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 Implementation #region Tree ///becomes false. /// Default implementation fires the event. /// /// 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); } } private bool ContainsSelection { get { return _bits[(int)Bits.ContainsSelection]; } set { _bits[(int)Bits.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) { IsExpanded = !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) { IsExpanded = true; e.Handled = true; } break; case Key.Subtract: if (CanExpandOnInput && IsExpanded) { IsExpanded = false; e.Handled = true; } break; case Key.Left: case Key.Right: if (LogicalLeft(e.Key)) { if (!IsControlKeyDown && CanExpandOnInput && IsExpanded) { if (IsFocused) { IsExpanded = false; } else { Focus(); } e.Handled = true; } } else { if (!IsControlKeyDown && CanExpandOnInput) { if (!IsExpanded) { IsExpanded = true; 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 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) { return FocusIntoItem(item); } } if (index == 0) { if (parent != ParentTreeView) { return parent.Focus(); } else { return true; // Prevents KeyboardNavigation from focusing one of our children } } } } return false; // Not handled } internal bool HandleDownKey() { if (AllowHandleKeyEvent(FocusNavigationDirection.Down)) { if (IsExpanded && CanExpand) { TreeViewItem item = ItemContainerGenerator.ContainerFromIndex(0) as TreeViewItem; if (item != null) { if (item.IsEnabled) { return item.Focus(); } else { item.FocusDown(); } } } else { 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 = null; // Find the last child in the subtree and focus it int index = -1; TreeViewItem parent = null; while (item != null) { if (item.IsEnabled) { if (!item.IsExpanded || !item.CanExpand) { return item.Focus(); } 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.Focus(); } return false; } internal bool FocusDown() { ItemsControl parent = ParentItemsControl; if (parent != null) { TreeViewItem item; int index = parent.ItemContainerGenerator.IndexFromContainer(this); int count = parent.Items.Count; while (index < count) { // Focus the next sibling index++; item = parent.ItemContainerGenerator.ContainerFromIndex(index) as TreeViewItem; if ((item != null) && item.IsEnabled && item.Focus()) { return true; } } // This item has no next sibling, focus the parent's next sibling item = parent as TreeViewItem; if (item != null) { return item.FocusDown(); } } return false; // Not handled } 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.IsExpanded = true; } parent = parent.ParentTreeViewItem; } // See FrameworkElement.BringIntoView() comments //[....], 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(); } } } 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(); } ////// 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)); } } #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 Data private enum Bits { ContainsSelection = 0x10, } // Packed boolean information private BitVector32 _bits = new BitVector32(0); 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
- HttpModuleCollection.cs
- ByteArrayHelperWithString.cs
- CodeDOMProvider.cs
- InputProviderSite.cs
- TagMapCollection.cs
- XsltInput.cs
- basevalidator.cs
- ZoomPercentageConverter.cs
- ObjectMemberMapping.cs
- Fx.cs
- TextElementEnumerator.cs
- RSAPKCS1KeyExchangeFormatter.cs
- StoragePropertyMapping.cs
- Operand.cs
- SolidBrush.cs
- Literal.cs
- _ReceiveMessageOverlappedAsyncResult.cs
- SessionEndingEventArgs.cs
- httpstaticobjectscollection.cs
- VirtualPathUtility.cs
- XmlFormatMapping.cs
- DirectoryInfo.cs
- CatalogPart.cs
- DropTarget.cs
- CompositeTypefaceMetrics.cs
- PathNode.cs
- DataGridViewSelectedColumnCollection.cs
- Compiler.cs
- BatchServiceHost.cs
- base64Transforms.cs
- AssertFilter.cs
- WeakReferenceEnumerator.cs
- XmlEventCache.cs
- RadioButtonFlatAdapter.cs
- ProfilePropertyMetadata.cs
- securitycriticaldata.cs
- EntityProviderServices.cs
- DataGridCellClipboardEventArgs.cs
- XmlSerializerVersionAttribute.cs
- MemberProjectedSlot.cs
- IDispatchConstantAttribute.cs
- DataPointer.cs
- BitmapEffectvisualstate.cs
- WsdlBuildProvider.cs
- ComponentResourceKeyConverter.cs
- ItemAutomationPeer.cs
- ImageSourceConverter.cs
- SQLBinary.cs
- XmlQueryTypeFactory.cs
- GenericEnumConverter.cs
- SqlConnectionStringBuilder.cs
- ChildChangedEventArgs.cs
- Vector3D.cs
- Duration.cs
- HTTPNotFoundHandler.cs
- ReadOnlyAttribute.cs
- BitmapPalette.cs
- TripleDES.cs
- TextRangeBase.cs
- TemplateKeyConverter.cs
- ClipboardProcessor.cs
- ProcessModelSection.cs
- IteratorDescriptor.cs
- HtmlInputSubmit.cs
- WpfGeneratedKnownProperties.cs
- ValueQuery.cs
- BehaviorService.cs
- ServiceContractListItem.cs
- FrameworkElement.cs
- PolicyVersionConverter.cs
- SizeChangedInfo.cs
- DocumentCollection.cs
- DeploymentSectionCache.cs
- BackgroundWorker.cs
- Privilege.cs
- SHA384Managed.cs
- SessionStateModule.cs
- RequiredFieldValidator.cs
- CriticalHandle.cs
- X509SecurityTokenProvider.cs
- TextBox.cs
- FileSystemInfo.cs
- StyleSheet.cs
- ComponentEditorPage.cs
- ProjectionNode.cs
- MatrixTransform3D.cs
- WindowsEditBox.cs
- DataSourceHelper.cs
- SizeAnimationClockResource.cs
- SerializationEventsCache.cs
- DurableDispatcherAddressingFault.cs
- ThreadAbortException.cs
- ImpersonateTokenRef.cs
- DrawListViewColumnHeaderEventArgs.cs
- SkewTransform.cs
- Avt.cs
- AnimationClockResource.cs
- SqlTransaction.cs
- RoleBoolean.cs
- CopyAction.cs