Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / System / Windows / Controls / VirtualizingStackPanel.cs / 4 / VirtualizingStackPanel.cs
//---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- //#define Profiling using MS.Internal; using MS.Utility; using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; using System.Diagnostics; using System.Windows.Controls.Primitives; using System.Windows.Media; using System.Windows.Threading; using System.Windows.Input; namespace System.Windows.Controls { ////// VirtualizingStackPanel is used to arrange children into single line. /// public class VirtualizingStackPanel : VirtualizingPanel, IScrollInfo { //------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------- #region Constructors ////// Default constructor. /// public VirtualizingStackPanel() { } #endregion Constructors //-------------------------------------------------------------------- // // Public Methods // //------------------------------------------------------------------- #region Public Methods //------------------------------------------------------------ // IScrollInfo Methods //------------------------------------------------------------ #region IScrollInfo Methods ////// Scroll content by one line to the top. /// public void LineUp() { SetVerticalOffset(VerticalOffset - ((Orientation == Orientation.Vertical) ? 1.0 : ScrollViewer._scrollLineDelta)); } ////// Scroll content by one line to the bottom. /// public void LineDown() { SetVerticalOffset(VerticalOffset + ((Orientation == Orientation.Vertical) ? 1.0 : ScrollViewer._scrollLineDelta)); } ////// Scroll content by one line to the left. /// public void LineLeft() { SetHorizontalOffset(HorizontalOffset - ((Orientation == Orientation.Horizontal) ? 1.0 : ScrollViewer._scrollLineDelta)); } ////// Scroll content by one line to the right. /// public void LineRight() { SetHorizontalOffset(HorizontalOffset + ((Orientation == Orientation.Horizontal) ? 1.0 : ScrollViewer._scrollLineDelta)); } ////// Scroll content by one page to the top. /// public void PageUp() { SetVerticalOffset(VerticalOffset - ViewportHeight); } ////// Scroll content by one page to the bottom. /// public void PageDown() { SetVerticalOffset(VerticalOffset + ViewportHeight); } ////// Scroll content by one page to the left. /// public void PageLeft() { SetHorizontalOffset(HorizontalOffset - ViewportWidth); } ////// Scroll content by one page to the right. /// public void PageRight() { SetHorizontalOffset(HorizontalOffset + ViewportWidth); } ////// Scroll content by one page to the top. /// public void MouseWheelUp() { SetVerticalOffset(VerticalOffset - SystemParameters.WheelScrollLines * ((Orientation == Orientation.Vertical) ? 1.0 : ScrollViewer._scrollLineDelta)); } ////// Scroll content by one page to the bottom. /// public void MouseWheelDown() { SetVerticalOffset(VerticalOffset + SystemParameters.WheelScrollLines * ((Orientation == Orientation.Vertical) ? 1.0 : ScrollViewer._scrollLineDelta)); } ////// Scroll content by one page to the left. /// public void MouseWheelLeft() { SetHorizontalOffset(HorizontalOffset - 3.0 * ((Orientation == Orientation.Horizontal) ? 1.0 : ScrollViewer._scrollLineDelta)); } ////// Scroll content by one page to the right. /// public void MouseWheelRight() { SetHorizontalOffset(HorizontalOffset + 3.0 * ((Orientation == Orientation.Horizontal) ? 1.0 : ScrollViewer._scrollLineDelta)); } ////// Set the HorizontalOffset to the passed value. /// public void SetHorizontalOffset(double offset) { EnsureScrollData(); double scrollX = ScrollContentPresenter.ValidateInputOffset(offset, "HorizontalOffset"); if (!DoubleUtil.AreClose(scrollX, _scrollData._offset.X)) { _scrollData._offset.X = scrollX; InvalidateMeasure(); } } ////// Set the VerticalOffset to the passed value. /// public void SetVerticalOffset(double offset) { EnsureScrollData(); double scrollY = ScrollContentPresenter.ValidateInputOffset(offset, "VerticalOffset"); if (!DoubleUtil.AreClose(scrollY, _scrollData._offset.Y)) { _scrollData._offset.Y = scrollY; InvalidateMeasure(); } } ////// VirtualizingStackPanel implementation of // The goal is to change offsets to bring the child into view, and return a rectangle in our space to make visible. // The rectangle we return is in the physical dimension the input target rect transformed into our pace. // In the logical dimension, it is our immediate child's rect. // Note: This code presently assumes we/children are layout clean. See work item 22269 for more detail. public Rect MakeVisible(Visual visual, Rect rectangle) { Vector newOffset = new Vector(); Rect newRect = new Rect(); Rect originalRect = rectangle; // We can only work on visuals that are us or children. // An empty rect has no size or position. We can't meaningfully use it. if ( rectangle.IsEmpty || visual == null || visual == (Visual)this || !this.IsAncestorOf(visual)) { return Rect.Empty; } #pragma warning disable 1634, 1691 #pragma warning disable 56506 // Compute the child's rect relative to (0,0) in our coordinate space. // This is a false positive by PreSharp. visual cannot be null because of the 'if' check above GeneralTransform childTransform = visual.TransformToAncestor(this); #pragma warning restore 56506 #pragma warning restore 1634, 1691 rectangle = childTransform.TransformBounds(rectangle); // We can't do any work unless we're scrolling. if (!IsScrolling) { return rectangle; } // Bring the target rect into view in the physical dimension. MakeVisiblePhysicalHelper(rectangle, ref newOffset, ref newRect); // Bring our child containing the visual into view. int childIndex = FindChildIndexThatParentsVisual(visual); MakeVisibleLogicalHelper(childIndex, rectangle, ref newOffset, ref newRect); // We have computed the scrolling offsets; validate and scroll to them. newOffset.X = ScrollContentPresenter.CoerceOffset(newOffset.X, _scrollData._extent.Width, _scrollData._viewport.Width); newOffset.Y = ScrollContentPresenter.CoerceOffset(newOffset.Y, _scrollData._extent.Height, _scrollData._viewport.Height); if (!DoubleUtil.AreClose(newOffset, _scrollData._offset)) { _scrollData._offset = newOffset; InvalidateMeasure(); OnScrollChange(); if (ScrollOwner != null) { // When layout gets updated it may happen that visual is obscured by a ScrollBar // We call MakeVisible again to make sure element is visible in this case ScrollOwner.MakeVisible(visual, originalRect); } } // Return the rectangle return newRect; } ///. /// /// Generates the item at the specified index and calls BringIntoView on it. /// /// Specify the item index that should become visible ////// Thrown if index is out of range /// protected internal override void BringIndexIntoView(int index) { UIElementCollection children = InternalChildren; if (index < 0 || index >= ItemCount) throw new ArgumentOutOfRangeException("index"); IItemContainerGenerator generator = Generator; int childIndex; GeneratorPosition position = IndexToGeneratorPositionForStart(index, out childIndex); using (generator.StartAt(position, GeneratorDirection.Forward, true)) { bool newlyRealized; UIElement child = generator.GenerateNext(out newlyRealized) as UIElement; if (child != null) { if (newlyRealized) { // A new container was generated, update the generated state if (childIndex >= children.Count) { VirtualizingPanel.AddInternalChild(children, child); } else { VirtualizingPanel.InsertInternalChild(children, childIndex, child); if (childIndex <= _firstVisibleChildIndex) { _firstVisibleChildIndex++; } } generator.PrepareItemContainer(child); } FrameworkElement element = child as FrameworkElement; if (element != null) { element.BringIntoView(); } } } } #endregion #endregion //------------------------------------------------------------------- // // Public Properties // //-------------------------------------------------------------------- #region Public Properties ////// Specifies dimension of children stacking. /// public Orientation Orientation { get { return (Orientation) GetValue(OrientationProperty); } set { SetValue(OrientationProperty, value); } } ////// This property is always true because this panel has vertical or horizontal orientation /// protected internal override bool HasLogicalOrientation { get { return true; } } ////// Orientation of the panel if its layout is in one dimension. /// Otherwise HasLogicalOrientation is false and LogicalOrientation should be ignored /// protected internal override Orientation LogicalOrientation { get { return this.Orientation; } } ////// DependencyProperty for public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register("Orientation", typeof(Orientation), typeof(VirtualizingStackPanel), new FrameworkPropertyMetadata(Orientation.Vertical, FrameworkPropertyMetadataOptions.AffectsMeasure, new PropertyChangedCallback(OnOrientationChanged)), new ValidateValueCallback(ScrollBar.IsValidOrientation)); ///property. /// /// Attached property for use on the ItemsControl that is the host for the items being /// presented by this panel. Use this property to turn virtualization on/off. /// public static readonly DependencyProperty IsVirtualizingProperty = DependencyProperty.RegisterAttached("IsVirtualizing", typeof(bool), typeof(VirtualizingStackPanel), new FrameworkPropertyMetadata(true)); ////// Retrieves the value for /// The object on which to query the value. ///. /// True if virtualizing, false otherwise. public static bool GetIsVirtualizing(DependencyObject o) { if (o == null) { throw new ArgumentNullException("o"); } return (bool)o.GetValue(IsVirtualizingProperty); } ////// Sets the value for /// The element on which to set the value. /// True if virtualizing, false otherwise. public static void SetIsVirtualizing(DependencyObject element, bool value) { if (element == null) { throw new ArgumentNullException("element"); } element.SetValue(IsVirtualizingProperty, value); } //----------------------------------------------------------- // IScrollInfo Properties //----------------------------------------------------------- #region IScrollInfo Properties ///. /// /// VirtualizingStackPanel reacts to this property by changing it's child measurement algorithm. /// If scrolling in a dimension, infinite space is allowed the child; otherwise, available size is preserved. /// [DefaultValue(false)] public bool CanHorizontallyScroll { get { if (_scrollData == null) { return false; } return _scrollData._allowHorizontal; } set { EnsureScrollData(); if (_scrollData._allowHorizontal != value) { _scrollData._allowHorizontal = value; InvalidateMeasure(); } } } ////// VirtualizingStackPanel reacts to this property by changing it's child measurement algorithm. /// If scrolling in a dimension, infinite space is allowed the child; otherwise, available size is preserved. /// [DefaultValue(false)] public bool CanVerticallyScroll { get { if (_scrollData == null) { return false; } return _scrollData._allowVertical; } set { EnsureScrollData(); if (_scrollData._allowVertical != value) { _scrollData._allowVertical = value; InvalidateMeasure(); } } } ////// ExtentWidth contains the horizontal size of the scrolled content element in 1/96" /// public double ExtentWidth { get { if (_scrollData == null) { return 0.0; } return _scrollData._extent.Width; } } ////// ExtentHeight contains the vertical size of the scrolled content element in 1/96" /// public double ExtentHeight { get { if (_scrollData == null) { return 0.0; } return _scrollData._extent.Height; } } ////// ViewportWidth contains the horizontal size of content's visible range in 1/96" /// public double ViewportWidth { get { if (_scrollData == null) { return 0.0; } return _scrollData._viewport.Width; } } ////// ViewportHeight contains the vertical size of content's visible range in 1/96" /// public double ViewportHeight { get { if (_scrollData == null) { return 0.0; } return _scrollData._viewport.Height; } } ////// HorizontalOffset is the horizontal offset of the scrolled content in 1/96". /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public double HorizontalOffset { get { if (_scrollData == null) { return 0.0; } return _scrollData._computedOffset.X; } } ////// VerticalOffset is the vertical offset of the scrolled content in 1/96". /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public double VerticalOffset { get { if (_scrollData == null) { return 0.0; } return _scrollData._computedOffset.Y; } } ////// ScrollOwner is the container that controls any scrollbars, headers, etc... that are dependant /// on this IScrollInfo's properties. /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public ScrollViewer ScrollOwner { get { EnsureScrollData(); return _scrollData._scrollOwner; } set { EnsureScrollData(); if (value != _scrollData._scrollOwner) { ResetScrolling(this); _scrollData._scrollOwner = value; } } } #endregion IScrollInfo Properties #endregion Public Properties //------------------------------------------------------------------- // // Public Events // //-------------------------------------------------------------------- #region Public Events ////// Called on the ItemsControl that owns this panel when an item is being re-virtualized. /// public static readonly RoutedEvent CleanUpVirtualizedItemEvent = EventManager.RegisterRoutedEvent("CleanUpVirtualizedItemEvent", RoutingStrategy.Direct, typeof(CleanUpVirtualizedItemEventHandler), typeof(VirtualizingStackPanel)); ////// Adds a handler for the CleanUpVirtualizedItem attached event /// /// DependencyObject that listens to this event /// Event Handler to be added public static void AddCleanUpVirtualizedItemHandler(DependencyObject element, CleanUpVirtualizedItemEventHandler handler) { FrameworkElement.AddHandler(element, CleanUpVirtualizedItemEvent, handler); } ////// Removes a handler for the CleanUpVirtualizedItem attached event /// /// DependencyObject that listens to this event /// Event Handler to be removed public static void RemoveCleanUpVirtualizedItemHandler(DependencyObject element, CleanUpVirtualizedItemEventHandler handler) { FrameworkElement.RemoveHandler(element, CleanUpVirtualizedItemEvent, handler); } ////// Called when an item is being re-virtualized. /// protected virtual void OnCleanUpVirtualizedItem(CleanUpVirtualizedItemEventArgs e) { ItemsControl itemsControl = ItemsControl.GetItemsOwner(this); if (itemsControl != null) { itemsControl.RaiseEvent(e); } } #endregion //------------------------------------------------------------------- // // Protected Methods // //-------------------------------------------------------------------- #region Protected Methods ////// General VirtualizingStackPanel layout behavior is to grow unbounded in the "stacking" direction (Size To Content). /// Children in this dimension are encouraged to be as large as they like. In the other dimension, /// VirtualizingStackPanel will assume the maximum size of its children. /// ////// When scrolling, VirtualizingStackPanel will not grow in layout size but effectively add the children on a z-plane which /// will probably be clipped by some parent (typically a ScrollContentPresenter) to Stack's size. /// /// Constraint ///Desired size protected override Size MeasureOverride(Size constraint) { #if Profiling if (Panel.IsAboutToGenerateContent(this)) return MeasureOverrideProfileStub(constraint); else return RealMeasureOverride(constraint); } // this is a handy place to start/stop profiling private Size MeasureOverrideProfileStub(Size constraint) { return RealMeasureOverride(constraint); } private Size RealMeasureOverride(Size constraint) { #endif UIElementCollection children = InternalChildren; Size stackDesiredSize = new Size(); Size layoutSlotSize = constraint; bool fHorizontal = (Orientation == Orientation.Horizontal); int firstViewport; // First child index in the viewport. int lastViewport = -1; // Last child index in the viewport. -1 indicates we have not yet iterated through the last child. double logicalVisibleSpace, childLogicalSize; bool etwTracingEnabled = IsScrolling && EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.normal); if (etwTracingEnabled) { EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.GENERICSTRINGGUID), MS.Utility.EventType.StartEvent, "VirtualizingStackPanel :MeasureOverride"); } // // Collect information from the ItemsControl, if there is one. // IItemContainerGenerator generator = Generator; ItemsControl itemsControl = ItemsControl.GetItemsOwner(this); int itemCount = (itemsControl != null) ? itemsControl.Items.Count : 0; bool isVirtualizing = (itemsControl != null) ? GetIsVirtualizing(itemsControl) : true; // // Initialize child sizing and iterator data // Allow children as much size as they want along the stack. // if (fHorizontal) { layoutSlotSize.Width = Double.PositiveInfinity; if (IsScrolling && CanVerticallyScroll) { layoutSlotSize.Height = Double.PositiveInfinity; } firstViewport = (IsScrolling) ? CoerceOffsetToInteger(_scrollData._offset.X, itemCount) : 0; logicalVisibleSpace = constraint.Width; } else { layoutSlotSize.Height = Double.PositiveInfinity; if (IsScrolling && CanHorizontallyScroll) { layoutSlotSize.Width = Double.PositiveInfinity; } firstViewport = (IsScrolling) ? CoerceOffsetToInteger(_scrollData._offset.Y, itemCount) : 0; logicalVisibleSpace = constraint.Height; } // // Figure out the position of the first visible item // GeneratorPosition startPos = IndexToGeneratorPositionForStart(isVirtualizing ? firstViewport : 0, out _firstVisibleChildIndex); int childIndex = _firstVisibleChildIndex; bool ranOutOfItems = true; _visibleCount = 0; if (itemCount > 0) { _afterTrail = 0; using (generator.StartAt(startPos, GeneratorDirection.Forward, true)) { for (int i = isVirtualizing ? firstViewport : 0, count = itemCount; i < count; ++i) { // Get next child. bool newlyRealized; UIElement child = generator.GenerateNext(out newlyRealized) as UIElement; if (child == null) { Debug.Assert(!newlyRealized, "The generator realized a null value."); // We reached the end of the items (because of a group) break; } if (!newlyRealized) { Debug.Assert(child == children[childIndex], "Wrong child was generated"); Debug.Assert(GetGeneratedIndex(childIndex) == i, "Wrong index for previously generated child"); } else { Debug.Assert(child != null, "Null child was generated"); if (childIndex >= children.Count) { VirtualizingPanel.AddInternalChild(children, child); } else { VirtualizingPanel.InsertInternalChild(children, childIndex, child); } generator.PrepareItemContainer(child); } childIndex++; _visibleCount++; // Measure the child. Size childDesiredSize = child.DesiredSize; child.Measure(layoutSlotSize); if (childDesiredSize != child.DesiredSize) { childDesiredSize = child.DesiredSize; // Reset the _maxDesiredSize cache if child DesiredSize changes if (_scrollData != null) _scrollData._maxDesiredSize = new Size(); } // Accumulate child size. if (fHorizontal) { stackDesiredSize.Width += childDesiredSize.Width; stackDesiredSize.Height = Math.Max(stackDesiredSize.Height, childDesiredSize.Height); childLogicalSize = childDesiredSize.Width; } else { stackDesiredSize.Width = Math.Max(stackDesiredSize.Width, childDesiredSize.Width); stackDesiredSize.Height += childDesiredSize.Height; childLogicalSize = childDesiredSize.Height; } // Adjust remaining viewport space if we are scrolling and within the viewport region. // While scrolling (not virtualizing), we always measure children before and after the viewport. if (IsScrolling && lastViewport == -1 && i >= firstViewport) { logicalVisibleSpace -= childLogicalSize; if (DoubleUtil.LessThanOrClose(logicalVisibleSpace, 0.0)) { lastViewport = i; } } // When scrolling, virtualizing, and beyond the first element, // then stop creating elements when out of space. if (IsScrolling && isVirtualizing && (i > firstViewport)) { // If begining of the item is outside the constraint if ((fHorizontal && (stackDesiredSize.Width - childDesiredSize.Width > constraint.Width)) || (!fHorizontal && (stackDesiredSize.Height - childDesiredSize.Height > constraint.Height))) { // We want to keep a focusable item after the end so that keyboard navigation // can work, but we want to limit that to FocusTrail number of items // in case all the items are not focusable. _afterTrail++; if ((_afterTrail >= FocusTrail) || Keyboard.IsFocusable(child)) { // Either we past the limit or the child was focusable ranOutOfItems = false; break; } // Loop around and generate another item } } } } } _visibleStart = firstViewport; // // Compute Scrolling stuff. // if (IsScrolling) { // Compute viewport and extent. Size viewport = constraint; Vector offset = _scrollData._offset; bool accumulateExtent = false; if (ScrollOwner != null) { accumulateExtent = ScrollOwner.InChildInvalidateMeasure; ScrollOwner.InChildInvalidateMeasure = false; } Size extent = new Size(); if (fHorizontal) { extent.Width = itemCount; extent.Height = accumulateExtent ? Math.Max(stackDesiredSize.Height, _scrollData._extent.Height) : stackDesiredSize.Height; } else { extent.Width = accumulateExtent ? Math.Max(stackDesiredSize.Width, _scrollData._extent.Width) : stackDesiredSize.Width; extent.Height = itemCount; } // If we have not yet set the last child in the viewport, set it to the last child. if (lastViewport == -1) { lastViewport = itemCount - 1; } if (ranOutOfItems) { // If we or children have resized, it's possible that we can now display more content. // This is true if we started at a nonzero offeset and still have space remaining. // In this case, we loop back through previous children until we run out of space. childIndex = isVirtualizing ? _firstVisibleChildIndex : firstViewport; while (childIndex > 0) { if (!PreviousChildIsGenerated(childIndex)) { GeneratePreviousChild(childIndex, layoutSlotSize); childIndex++; // We just inserted a child, so increment the index } else if (childIndex <= _firstVisibleChildIndex) { // This child has not been measured yet children[childIndex - 1].Measure(layoutSlotSize); } double projectedLogicalVisibleSpace = logicalVisibleSpace; Size childDesiredSize = children[childIndex - 1].DesiredSize; if (fHorizontal) { projectedLogicalVisibleSpace -= childDesiredSize.Width; } else { projectedLogicalVisibleSpace -= childDesiredSize.Height; } // If we have run out of room, break. if (DoubleUtil.LessThan(projectedLogicalVisibleSpace, 0.0)) { break; } // Account for the child in the panel's desired size if (fHorizontal) { stackDesiredSize.Width += childDesiredSize.Width; stackDesiredSize.Height = Math.Max(stackDesiredSize.Height, childDesiredSize.Height); } else { stackDesiredSize.Width = Math.Max(stackDesiredSize.Width, childDesiredSize.Width); stackDesiredSize.Height += childDesiredSize.Height; } // Adjust viewport childIndex--; logicalVisibleSpace = projectedLogicalVisibleSpace; } if ((childIndex < _firstVisibleChildIndex) || !isVirtualizing) { _firstVisibleChildIndex = childIndex; } _visibleStart = firstViewport = (GetGeneratedCount(children) == 0) ? 0 : GetGeneratedIndex(_firstVisibleChildIndex); } EnsureTopCapGenerated(layoutSlotSize); int logicalExtent = itemCount; int logicalViewport = lastViewport - firstViewport; // We are conservative when estimating a viewport, not including the last element in case it is only partially visible. // We want to count it if it is fully visible (>= 0 space remaining) or the only element in the viewport. if (logicalViewport == 0 || DoubleUtil.GreaterThanOrClose(logicalVisibleSpace, 0.0)) { logicalViewport++; } if (fHorizontal) { _scrollData._physicalViewport = viewport.Width; viewport.Width = logicalViewport; offset.X = firstViewport; offset.Y = Math.Max(0, Math.Min(offset.Y, extent.Height - viewport.Height)); // In case last item is visible because we scroll all the way to the right and scrolling is on // we want desired size not to be smaller than constraint to avoid another relayout if (logicalExtent > logicalViewport && !Double.IsPositiveInfinity(constraint.Width)) { stackDesiredSize.Width = constraint.Width; } } else { _scrollData._physicalViewport = viewport.Height; viewport.Height = logicalViewport; offset.Y = firstViewport; offset.X = Math.Max(0, Math.Min(offset.X, extent.Width - viewport.Width)); // In case last item is visible because we scroll all the way to the bottom and scrolling is on // we want desired size not to be smaller than constraint to avoid another relayout if (logicalExtent > logicalViewport && !Double.IsPositiveInfinity(constraint.Height)) { stackDesiredSize.Height = constraint.Height; } } // Since we can offset and clip our content, we never need to be larger than the parent suggestion. // If we returned the full size of the content, we would always be so big we didn't need to scroll. :) stackDesiredSize.Width = Math.Min(stackDesiredSize.Width, constraint.Width); stackDesiredSize.Height = Math.Min(stackDesiredSize.Height, constraint.Height); // When scrolling, the maximum horizontal or vertical size of items can cause the desired size of the // panel to change, which can cause the owning ScrollViewer re-layout as well when it is not necessary. // We will thus remember the maximum desired size and always return that. The actual arrangement and // clipping still be calculated from actual scroll data values. // The maximum desired size is reset when the items change. _scrollData._maxDesiredSize.Width = Math.Max(stackDesiredSize.Width, _scrollData._maxDesiredSize.Width); _scrollData._maxDesiredSize.Height = Math.Max(stackDesiredSize.Height, _scrollData._maxDesiredSize.Height); stackDesiredSize = _scrollData._maxDesiredSize; // Verify Scroll Info, invalidate ScrollOwner if necessary. VerifyScrollingData(viewport, extent, offset); } if (isVirtualizing) { EnsureCleanupOperation(false /* delay */); } if (etwTracingEnabled) { EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.GENERICSTRINGGUID), MS.Utility.EventType.EndEvent, "VirtualizingStackPanel :MeasureOverride"); } return stackDesiredSize; } private void EnsureCleanupOperation(bool delay) { if (delay) { bool noPendingOperations = true; if (_cleanupOperation != null) { noPendingOperations = _cleanupOperation.Abort(); if (noPendingOperations) { _cleanupOperation = null; } } if (noPendingOperations && (_cleanupDelay == null)) { _cleanupDelay = new DispatcherTimer(); _cleanupDelay.Tick += new EventHandler(OnDelayCleanup); _cleanupDelay.Interval = TimeSpan.FromMilliseconds(500.0); _cleanupDelay.Start(); } } else { if ((_cleanupOperation == null) && (_cleanupDelay == null)) { _cleanupOperation = Dispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(OnCleanUp), null); } } } private bool PreviousChildIsGenerated(int childIndex) { GeneratorPosition position = new GeneratorPosition(childIndex, 0); position = Generator.GeneratorPositionFromIndex(Generator.IndexFromGeneratorPosition(position) - 1); return (position.Offset == 0 && position.Index >= 0); } private UIElement GeneratePreviousChild(int childIndex, Size layoutSlotSize) { int newIndex = Generator.IndexFromGeneratorPosition(new GeneratorPosition(childIndex, 0)) - 1; if (newIndex >= 0) { UIElement child; IItemContainerGenerator generator = Generator; ItemsControl itemsControl = ItemsControl.GetItemsOwner(this); UIElementCollection children = InternalChildren; int newGeneratedIndex; GeneratorPosition newStartPos = IndexToGeneratorPositionForStart(newIndex, out newGeneratedIndex); using (generator.StartAt(newStartPos, GeneratorDirection.Forward, true)) { bool newlyRealized; child = generator.GenerateNext(out newlyRealized) as UIElement; Debug.Assert(child != null, "Null child was generated"); Debug.Assert(newlyRealized, "New child should have been realized"); VirtualizingPanel.InsertInternalChild(children, childIndex, child); generator.PrepareItemContainer(child); if (childIndex <= _firstVisibleChildIndex) { _firstVisibleChildIndex++; } child.Measure(layoutSlotSize); } return child; } return null; } ////// Called when the Items collection associated with the containing ItemsControl changes. /// /// sender /// Event arguments protected override void OnItemsChanged(object sender, ItemsChangedEventArgs args) { base.OnItemsChanged(sender, args); bool resetMaximumDesiredSize = false; switch (args.Action) { case NotifyCollectionChangedAction.Remove: OnItemsRemove(args); resetMaximumDesiredSize = true; break; case NotifyCollectionChangedAction.Replace: OnItemsReplace(args); resetMaximumDesiredSize = true; break; case NotifyCollectionChangedAction.Move: OnItemsMove(args); break; case NotifyCollectionChangedAction.Reset: resetMaximumDesiredSize = true; break; } if (resetMaximumDesiredSize && IsScrolling) { // The items changed such that the maximum size may no longer be valid. // The next layout pass will update this value. _scrollData._maxDesiredSize = new Size(); } } ////// Called when the UI collection of children is cleared by the base Panel class. /// protected override void OnClearChildren() { base.OnClearChildren(); _visibleStart = _firstVisibleChildIndex = _visibleCount = 0; } private void OnItemsRemove(ItemsChangedEventArgs args) { RemoveChildRange(args.Position, args.ItemCount, args.ItemUICount); } private void OnItemsReplace(ItemsChangedEventArgs args) { RemoveChildRange(args.Position, args.ItemCount, args.ItemUICount); } private void OnItemsMove(ItemsChangedEventArgs args) { RemoveChildRange(args.OldPosition, args.ItemCount, args.ItemUICount); } private void RemoveChildRange(GeneratorPosition position, int itemCount, int itemUICount) { UIElementCollection children = InternalChildren; int pos = position.Index; if (position.Offset > 0) { // An item is being removed after the one at the index pos++; } if (pos < GetGeneratedCount(children)) { int uiCount = itemUICount; Debug.Assert((itemCount == itemUICount) || (itemUICount == 0), "Both ItemUICount and ItemCount should be equal or ItemUICount should be 0."); if (uiCount > 0) { VirtualizingPanel.RemoveInternalChildRange(children, pos, uiCount); } } } private GeneratorPosition IndexToGeneratorPositionForStart(int index, out int childIndex) { IItemContainerGenerator generator = Generator; GeneratorPosition position = (generator != null) ? generator.GeneratorPositionFromIndex(index) : new GeneratorPosition(-1, index + 1); // determine the position in the children collection for the first // generated container. This assumes that generator.StartAt will be called // with direction=Forward and allowStartAtRealizedItem=true. childIndex = (position.Offset == 0) ? position.Index : position.Index + 1; return position; } private void OnDelayCleanup(object sender, EventArgs e) { Debug.Assert(_cleanupDelay != null); bool needsMoreCleanup = false; try { needsMoreCleanup = CleanUp(); } finally { // Cleanup the timer if more cleanup is unnecessary if (!needsMoreCleanup) { _cleanupDelay.Stop(); _cleanupDelay = null; } } } private object OnCleanUp(object args) { Debug.Assert(_cleanupOperation != null); bool needsMoreCleanup = false; try { needsMoreCleanup = CleanUp(); } finally { // Keeping this non-null until here in case cleaning up causes re-entrancy _cleanupOperation = null; } if (needsMoreCleanup) { EnsureCleanupOperation(true /* delay */); } return null; } private bool CleanUp() { ItemsControl itemsControl = ItemsControl.GetItemsOwner(this); if ((itemsControl != null) && !GetIsVirtualizing(itemsControl)) { // Virtualization is turned off, no need to cleanup. return false; } int startMilliseconds = Environment.TickCount; bool needsMoreCleanup = false; UIElementCollection children = InternalChildren; int minDesiredGenerated = MinDesiredGenerated; int maxDesiredGenerated = MaxDesiredGenerated; int pageSize = maxDesiredGenerated - minDesiredGenerated; int extraChildren = GetGeneratedCount(children) - pageSize; if (extraChildren > (pageSize * 2)) { if ((Mouse.LeftButton == MouseButtonState.Pressed) && (extraChildren < 1000)) { // An optimization for when we are dragging the mouse. needsMoreCleanup = true; } else { bool trailingFocus = IsKeyboardFocusWithin; bool keepForwardTrail = false; int focusIndex = -1; IItemContainerGenerator generator = Generator; int cleanupRangeStart = 0; int cleanupCount = 0; int lastGeneratedIndex = -1; int counterAdjust; for (int i = 0; i < GetGeneratedCount(children); i++) { // It is possible for TickCount to wrap around about every 30 days. // If that were to occur, then this particular cleanup may not be interrupted. // That is OK since the worst that can happen is that there is more of a stutter than normal. int totalMilliseconds = Environment.TickCount - startMilliseconds; if ((totalMilliseconds > 50) && (cleanupCount > 0)) { // Cleanup has been working for 50ms already and the user might start // noticing a lag. Stop cleaning up and release the thread for other work. // Cleanup will continue later. // Don't break out until after at least one item has been found to cleanup. // Otherwise, we might end up in an infinite loop. needsMoreCleanup = true; break; } int childIndex = i; if (trailingFocus) { // Focus lies somewhere within the panel, but it has not been found yet. UIElement child = children[i]; if (child.IsKeyboardFocusWithin) { // Focus has been found, we can now re-virtualize items before the focus. trailingFocus = false; keepForwardTrail = true; focusIndex = i; if (i > 0) { // Go through the trailing items and find a focusable item to keep. int trailIndex = i - 1; int end = Math.Max(0, i - FocusTrail); for (; trailIndex >= end; trailIndex--) { child = children[trailIndex]; if (Keyboard.IsFocusable(child)) { trailIndex--; break; } } // The rest of the trailing items can be re-virtualized. for (childIndex = end; childIndex <= trailIndex; childIndex++) { ManageCleanup( children, itemsControl, generator, childIndex, minDesiredGenerated, maxDesiredGenerated, ref childIndex, ref cleanupRangeStart, ref cleanupCount, ref lastGeneratedIndex, out counterAdjust); if (counterAdjust > 0) { i -= counterAdjust; trailIndex -= counterAdjust; } } if (cleanupCount > 0) { // Cleanup the last batch for the focused item CleanupRange(children, generator, cleanupRangeStart, cleanupCount); i -= cleanupCount; cleanupCount = 0; } cleanupRangeStart = i + 1; // At this point, we are caught up and should go to the next item continue; } } else if (i >= FocusTrail) { childIndex = i - FocusTrail; } else { continue; } } if (keepForwardTrail) { // Find a focusable item after the focused item to keep if (childIndex <= (focusIndex + FocusTrail)) { UIElement child = children[childIndex]; if (Keyboard.IsFocusable(child)) { // A focusable item was found, all items after this one can be re-virtualized keepForwardTrail = false; cleanupRangeStart = childIndex + 1; cleanupCount = 0; } continue; } else { keepForwardTrail = false; } } ManageCleanup( children, itemsControl, generator, childIndex, minDesiredGenerated, maxDesiredGenerated, ref i, ref cleanupRangeStart, ref cleanupCount, ref lastGeneratedIndex, out counterAdjust); } if (cleanupCount > 0) { // Cleanup the final batch CleanupRange(children, generator, cleanupRangeStart, cleanupCount); } } } return needsMoreCleanup; } private void ManageCleanup( UIElementCollection children, ItemsControl itemsControl, IItemContainerGenerator generator, int childIndex, int minDesiredGenerated, int maxDesiredGenerated, ref int counter, ref int cleanupRangeStart, ref int cleanupCount, ref int lastGeneratedIndex, out int counterAdjust) { counterAdjust = 0; bool performCleanup = false; bool countThisChild = false; int generatedIndex = GetGeneratedIndex(childIndex); if (OutsideMinMax(generatedIndex, minDesiredGenerated, maxDesiredGenerated) && NotifyCleanupItem(childIndex, children, itemsControl, generator)) { // The item can be re-virtualized. if ((generatedIndex - lastGeneratedIndex) == 1) { // Add another to the current batch. cleanupCount++; } else { // There was a gap in generated items. Cleanup any from the previous batch. performCleanup = countThisChild = true; } } else { // The item cannot be re-virtualized. Cleanup any from the previous batch. performCleanup = true; } if (performCleanup) { // Cleanup a batch of items if (cleanupCount > 0) { CleanupRange(children, generator, cleanupRangeStart, cleanupCount); counterAdjust = cleanupCount; counter -= counterAdjust; childIndex -= counterAdjust; cleanupCount = 0; } if (countThisChild) { // The current child was not included in the batch and should be saved for later cleanupRangeStart = childIndex; cleanupCount = 1; } else { // The next child will start the next batch. cleanupRangeStart = childIndex + 1; } } lastGeneratedIndex = generatedIndex; } private bool NotifyCleanupItem(int childIndex, UIElementCollection children, ItemsControl itemsControl, IItemContainerGenerator generator) { UIElement child = children[childIndex]; CleanUpVirtualizedItemEventArgs e = new CleanUpVirtualizedItemEventArgs(itemsControl.ItemContainerGenerator.ItemFromContainer(child), child); e.Source = this; OnCleanUpVirtualizedItem(e); return !e.Cancel; } private void CleanupRange(UIElementCollection children, IItemContainerGenerator generator, int startIndex, int count) { // Remove the desired range of children VirtualizingPanel.RemoveInternalChildRange(children, startIndex, count); generator.Remove(new GeneratorPosition(startIndex, 0), count); // Update the index of the first visible generated child if (startIndex < _firstVisibleChildIndex) { int endIndex = startIndex + count - 1; if (endIndex < _firstVisibleChildIndex) { // The first visible index is after the items that were removed _firstVisibleChildIndex -= count; } else { // The first visible index was within the items that were removed _firstVisibleChildIndex = startIndex; } } } private static bool OutsideMinMax(int i, int min, int max) { return ((i < min) || (i > max)); } private void EnsureTopCapGenerated(Size layoutSlotSize) { // Ensure that a focusable item is generated above the first visible item // so that keyboard navigation works. _beforeTrail = 0; if (_visibleStart > 0) { int childIndex = _firstVisibleChildIndex; UIElementCollection children = InternalChildren; UIElement child; // At most, we will search FocusTrail number of items for a focusable item for (; _beforeTrail < FocusTrail; _beforeTrail++) { if (PreviousChildIsGenerated(childIndex)) { // The previous child is already generated, check its focusability childIndex--; child = children[childIndex]; } else { // Generate the previous child child = GeneratePreviousChild(childIndex, layoutSlotSize); } if ((child == null) || Keyboard.IsFocusable(child)) { // Either a focusable item was found, or no child was generated _beforeTrail++; break; } } } } private int MinDesiredGenerated { get { return Math.Max(0, _visibleStart - _beforeTrail); } } private int MaxDesiredGenerated { get { return Math.Min(ItemCount, _visibleStart + _visibleCount + _afterTrail); } } private int ItemCount { get { ItemsControl itemsControl = ItemsControl.GetItemsOwner(this); return (itemsControl != null) ? itemsControl.Items.Count : 0; } } ////// Content arrangement. /// /// Arrange size protected override Size ArrangeOverride(Size arrangeSize) { ItemsControl itemsControl = ItemsControl.GetItemsOwner(this); bool isVirtualizing = (itemsControl != null) ? GetIsVirtualizing(itemsControl) : true; bool fHorizontal = (Orientation == Orientation.Horizontal); Rect rcChild = new Rect(arrangeSize); double previousChildSize = 0.0; bool etwTracingEnabled = IsScrolling && EventTrace.IsEnabled(EventTrace.Flags.performance, EventTrace.Level.normal); if (etwTracingEnabled) { EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.GENERICSTRINGGUID), MS.Utility.EventType.StartEvent, "VirtualizingStackPanel :ArrangeOverride"); } // // Compute scroll offset and seed it into rcChild. // if (IsScrolling) { if (fHorizontal) { rcChild.X = ComputePhysicalFromLogicalOffset(isVirtualizing ? _firstVisibleChildIndex : _scrollData._computedOffset.X, true); rcChild.Y = -1.0 * _scrollData._computedOffset.Y; } else { rcChild.X = -1.0 * _scrollData._computedOffset.X; rcChild.Y = ComputePhysicalFromLogicalOffset(isVirtualizing ? _firstVisibleChildIndex : _scrollData._computedOffset.Y, false); } } // // Arrange and Position Children. // int childrenCount = InternalChildren.Count; for (int i = 0; i < childrenCount; ++i) { UIElement child = InternalChildren[i]; if (child != null) { if (fHorizontal) { rcChild.X += previousChildSize; previousChildSize = child.DesiredSize.Width; rcChild.Width = previousChildSize; rcChild.Height = Math.Max(arrangeSize.Height, child.DesiredSize.Height); } else { rcChild.Y += previousChildSize; previousChildSize = child.DesiredSize.Height; rcChild.Height = previousChildSize; rcChild.Width = Math.Max(arrangeSize.Width, child.DesiredSize.Width); } child.Arrange(rcChild); } } if (etwTracingEnabled) { EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.GENERICSTRINGGUID), MS.Utility.EventType.EndEvent, "VirtualizingStackPanel :ArrangeOverride"); } return arrangeSize; } #endregion Protected Methods //------------------------------------------------------ // // Private Methods // //----------------------------------------------------- #region Private Methods private void EnsureScrollData() { if (_scrollData == null) { _scrollData = new ScrollData(); } } private static void ResetScrolling(VirtualizingStackPanel element) { element.InvalidateMeasure(); // Clear scrolling data. Because of thrash (being disconnected & reconnected, &c...), we may if (element.IsScrolling) { element._scrollData.ClearLayout(); } } // OnScrollChange is an override called whenever the IScrollInfo exposed scrolling state changes on this element. // At the time this method is called, scrolling state is in its new, valid state. private void OnScrollChange() { if (ScrollOwner != null) { ScrollOwner.InvalidateScrollInfo(); } } private void VerifyScrollingData(Size viewport, Size extent, Vector offset) { bool fValid = true; Debug.Assert(IsScrolling); fValid &= DoubleUtil.AreClose(viewport, _scrollData._viewport); fValid &= DoubleUtil.AreClose(extent, _scrollData._extent); fValid &= DoubleUtil.AreClose(offset, _scrollData._computedOffset); _scrollData._offset = offset; if (!fValid) { _scrollData._viewport = viewport; _scrollData._extent = extent; _scrollData._computedOffset = offset; OnScrollChange(); } } // Translates a logical (child index) offset to a physical (1/96") when scrolling. // If virtualizing, it makes the assumption that the logicalOffset is always the first in the visual collection // and thus returns 0. // If not virtualizing, it assumes that children are Measure clean; should only be called after running Measure. private double ComputePhysicalFromLogicalOffset(double logicalOffset, bool fHorizontal) { double physicalOffset = 0.0; int childrenCount = InternalChildren.Count; Debug.Assert(logicalOffset == 0 || (logicalOffset > 0 && logicalOffset < childrenCount)); for (int i = 0; i < logicalOffset; i++) { physicalOffset -= (fHorizontal) ? InternalChildren[i].DesiredSize.Width : InternalChildren[i].DesiredSize.Height; } return physicalOffset; } private int FindChildIndexThatParentsVisual(Visual v) { DependencyObject child = v; DependencyObject parent = VisualTreeHelper.GetParent(child); while (parent != this) { child = parent; parent = VisualTreeHelper.GetParent(child); } UIElementCollection children = InternalChildren; for (int i = 0; i < children.Count; i++) { if (children[i] == child) { return GetGeneratedIndex(i); } } return -1; } private void MakeVisiblePhysicalHelper(Rect r, ref Vector newOffset, ref Rect newRect) { double viewportOffset; double viewportSize; double targetRectOffset; double targetRectSize; double minPhysicalOffset; bool fHorizontal = (Orientation == Orientation.Horizontal); if (fHorizontal) { viewportOffset = _scrollData._computedOffset.Y; viewportSize = ViewportHeight; targetRectOffset = r.Y; targetRectSize = r.Height; } else { viewportOffset = _scrollData._computedOffset.X; viewportSize = ViewportWidth; targetRectOffset = r.X; targetRectSize = r.Width; } targetRectOffset += viewportOffset; minPhysicalOffset = ScrollContentPresenter.ComputeScrollOffsetWithMinimalScroll( viewportOffset, viewportOffset + viewportSize, targetRectOffset, targetRectOffset + targetRectSize); // Compute the visible rectangle of the child relative to the viewport. double left = Math.Max(targetRectOffset, minPhysicalOffset); targetRectSize = Math.Max(Math.Min(targetRectSize + targetRectOffset, minPhysicalOffset + viewportSize) - left, 0); targetRectOffset = left; targetRectOffset -= viewportOffset; if (fHorizontal) { newOffset.Y = minPhysicalOffset; newRect.Y = targetRectOffset; newRect.Height = targetRectSize; } else { newOffset.X = minPhysicalOffset; newRect.X = targetRectOffset; newRect.Width = targetRectSize; } } private void MakeVisibleLogicalHelper(int childIndex, Rect r, ref Vector newOffset, ref Rect newRect) { bool fHorizontal = (Orientation == Orientation.Horizontal); int firstChildInView; int newFirstChild; int viewportSize; double childOffsetWithinViewport = r.Y; if (fHorizontal) { firstChildInView = (int)_scrollData._computedOffset.X; viewportSize = (int)_scrollData._viewport.Width; } else { firstChildInView = (int)_scrollData._computedOffset.Y; viewportSize = (int)_scrollData._viewport.Height; } newFirstChild = firstChildInView; // If the target child is before the current viewport, move the viewport to put the child at the top. if (childIndex < firstChildInView) { childOffsetWithinViewport = 0; newFirstChild = childIndex; } // If the target child is after the current viewport, move the viewport to put the child at the bottom. else if (childIndex > firstChildInView + viewportSize - 1) { newFirstChild = childIndex - viewportSize + 1; double pixelSize = fHorizontal ? ActualWidth : ActualHeight; childOffsetWithinViewport = pixelSize * (1.0 - (1.0 / viewportSize)); } if (fHorizontal) { newOffset.X = newFirstChild; newRect.X = childOffsetWithinViewport; newRect.Width = r.Width; } else { newOffset.Y = newFirstChild; newRect.Y = childOffsetWithinViewport; newRect.Height = r.Height; } } static private int CoerceOffsetToInteger(double offset, int numberOfItems) { int iNewOffset; if (Double.IsNegativeInfinity(offset)) { iNewOffset = 0; } else if (Double.IsPositiveInfinity(offset)) { iNewOffset = numberOfItems - 1; } else { iNewOffset = (int)offset; iNewOffset = Math.Max(Math.Min(numberOfItems - 1, iNewOffset), 0); } return iNewOffset; } private int GetGeneratedCount(UIElementCollection children) { return IsItemsHost ? children.Count : 0; } private int GetGeneratedIndex(int childIndex) { return Generator.IndexFromGeneratorPosition(new GeneratorPosition(childIndex, 0)); } //------------------------------------------------------------ // Avalon Property Callbacks/Overrides //----------------------------------------------------------- #region Avalon Property Callbacks/Overrides ////// private static void OnOrientationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { // Since Orientation is so essential to logical scrolling/virtualization, we synchronously check if // the new value is different and clear all scrolling data if so. ResetScrolling(d as VirtualizingStackPanel); } #endregion #endregion Private Methods //----------------------------------------------------- // // Private Properties // //----------------------------------------------------- #region Private Properties private bool IsScrolling { get { return (_scrollData != null) && (_scrollData._scrollOwner != null); } } #endregion Private Properties //------------------------------------------------------ // // Private Fields // //----------------------------------------------------- #region Private Fields // Logical scrolling and virtualization data. private ScrollData _scrollData; // Virtualization state private int _visibleStart; private int _visibleCount; private int _firstVisibleChildIndex; // Cleanup private DispatcherOperation _cleanupOperation; private DispatcherTimer _cleanupDelay; private int _beforeTrail = 0; private int _afterTrail = 0; private const int FocusTrail = 5; // The maximum number of items off the edge we will generate to get a focused item (so that keyboard navigation can work) #endregion Private Fields //------------------------------------------------------ // // Private Structures / Classes // //------------------------------------------------------ #region Private Structures Classes //----------------------------------------------------------- // ScrollData class //------------------------------------------------------------ #region ScrollData // Helper class to hold scrolling data. // This class exists to reduce working set when VirtualizingStackPanel is used outside a scrolling situation. // Standard "extra pointer always for less data sometimes" cache savings model: // !Scroll [1xReference] // Scroll [1xReference] + [6xDouble + 1xReference] private class ScrollData { // Clears layout generated data. // Does not clear scrollOwner, because unless resetting due to a scrollOwner change, we won't get reattached. internal void ClearLayout() { _offset = new Vector(); _viewport = _extent = _maxDesiredSize = new Size(); _physicalViewport = 0; } // For Stack/Flow, the two dimensions of properties are in different units: // 1. The "logically scrolling" dimension uses items as units. // 2. The other dimension physically scrolls. Units are in Avalon pixels (1/96"). internal bool _allowHorizontal; internal bool _allowVertical; internal Vector _offset; // Scroll offset of content. Positive corresponds to a visually upward offset. internal Vector _computedOffset = new Vector(0,0); internal Size _viewport; // ViewportSize is in {pixels x items} (or vice-versa). internal Size _extent; // Extent is the total number of children (logical dimension) or physical size internal double _physicalViewport; // The physical size of the viewport for the items dimension above. internal ScrollViewer _scrollOwner; // ScrollViewer to which we're attached. internal Size _maxDesiredSize; // Hold onto the maximum desired size to avoid re-laying out the parent ScrollViewer. } #endregion ScrollData #endregion Private Structures Classes } } // 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
- PenContext.cs
- CodeDOMUtility.cs
- HotSpotCollection.cs
- MergeFilterQuery.cs
- DataServiceQueryException.cs
- Vector3DKeyFrameCollection.cs
- DeclarationUpdate.cs
- xmlglyphRunInfo.cs
- DashStyles.cs
- InternalException.cs
- SignedXml.cs
- HttpListenerPrefixCollection.cs
- HwndStylusInputProvider.cs
- StringStorage.cs
- LinqDataSourceUpdateEventArgs.cs
- NumberSubstitution.cs
- HashSetEqualityComparer.cs
- SelectionRangeConverter.cs
- LogLogRecordHeader.cs
- TrustManagerMoreInformation.cs
- RootNamespaceAttribute.cs
- namescope.cs
- SamlEvidence.cs
- ButtonBaseAdapter.cs
- PropertyTabAttribute.cs
- HtmlString.cs
- WorkflowWebHostingModule.cs
- HostExecutionContextManager.cs
- NativeWindow.cs
- HttpCacheVary.cs
- FtpRequestCacheValidator.cs
- TokenizerHelper.cs
- RelationshipEndCollection.cs
- DbgUtil.cs
- Asn1IntegerConverter.cs
- PolicyValidator.cs
- SignatureDescription.cs
- ControlAdapter.cs
- Matrix3DConverter.cs
- WebPartUserCapability.cs
- ObjectPersistData.cs
- SafeNativeMethods.cs
- QilSortKey.cs
- _AcceptOverlappedAsyncResult.cs
- CommunicationObject.cs
- Timer.cs
- ElapsedEventArgs.cs
- DataTableReader.cs
- TextBox.cs
- HttpResponseHeader.cs
- SqlParameterCollection.cs
- HttpModulesSection.cs
- ConditionCollection.cs
- SyncOperationState.cs
- WebHostUnsafeNativeMethods.cs
- SamlSubject.cs
- CompiledQuery.cs
- PersonalizableAttribute.cs
- ClientTargetCollection.cs
- TemplateBindingExtensionConverter.cs
- EncodingInfo.cs
- Exception.cs
- MetadataItemEmitter.cs
- ConstrainedDataObject.cs
- QualificationDataItem.cs
- ServicesUtilities.cs
- RadioButton.cs
- PassportIdentity.cs
- ConsoleEntryPoint.cs
- QilFunction.cs
- MailWriter.cs
- ByeOperationCD1AsyncResult.cs
- MissingMethodException.cs
- PagedControl.cs
- XmlElementList.cs
- CalendarDateChangedEventArgs.cs
- EmbeddedObject.cs
- ObjectPersistData.cs
- SqlDataSourceConfigureFilterForm.cs
- ChangePassword.cs
- DiscoveryOperationContext.cs
- RightNameExpirationInfoPair.cs
- DefaultIfEmptyQueryOperator.cs
- Axis.cs
- Calendar.cs
- InputLanguageManager.cs
- Image.cs
- TransformGroup.cs
- ListBindableAttribute.cs
- DataSourceControl.cs
- Clock.cs
- HtmlInputText.cs
- BeginCreateSecurityTokenRequest.cs
- ObjectListItem.cs
- TextMetrics.cs
- ZipFileInfoCollection.cs
- TableHeaderCell.cs
- COAUTHIDENTITY.cs
- NameScopePropertyAttribute.cs
- SiteMapPath.cs