Пример #1
0
        public void UpdatePin(UIElement element, bool addPin)
        {
            var parent             = CachedVisualTreeHelpers.GetParent(element);
            DependencyObject child = element;

            while (parent != null)
            {
                if (parent is ItemsRepeater repeater)
                {
                    var virtInfo = ItemsRepeater.GetVirtualizationInfo((UIElement)child);
                    if (virtInfo.IsRealized)
                    {
                        if (addPin)
                        {
                            virtInfo.AddPin();
                        }
                        else if (virtInfo.IsPinned)
                        {
                            if (virtInfo.RemovePin() == 0)
                            {
                                // ElementFactory is invoked during the measure pass.
                                // We will clear the element then.
                                repeater.InvalidateMeasure();
                            }
                        }
                    }
                }

                child  = parent;
                parent = CachedVisualTreeHelpers.GetParent(child);
            }
        }
Пример #2
0
        private void OnHideAnimationCompleted(ElementAnimator sender, UIElement element)
        {
            if (CachedVisualTreeHelpers.GetParent(element) == m_owner)
            {
                m_owner.ViewManager.ClearElementToElementFactory(element);

                // Invalidate arrange so that repeater can arrange this element off-screen.
                m_owner.InvalidateArrange();
            }
        }
Пример #3
0
        private void UpdateFocusedElement()
        {
            UIElement focusedElement = null;

            // auto child = winrt::FocusManager::GetFocusedElement().as<winrt::DependencyObject>();
            var child = Keyboard.FocusedElement as DependencyObject;

            if (child != null)
            {
                var parent = CachedVisualTreeHelpers.GetParent(child);
                var owner  = m_owner;

                // Find out if the focused element belongs to one of our direct
                // children.
                while (parent != null)
                {
                    var repeater = parent as ItemsRepeater;
                    if (repeater != null)
                    {
                        var element = child as UIElement;
                        if (repeater == owner && ItemsRepeater.GetVirtualizationInfo(element).IsRealized)
                        {
                            focusedElement = element;
                        }

                        break;
                    }

                    child  = parent;
                    parent = CachedVisualTreeHelpers.GetParent(child);
                }
            }

            // If the focused element has changed,
            // we need to unpin the old one and pin the new one.
            if (m_lastFocusedElement != focusedElement)
            {
                if (m_lastFocusedElement != null)
                {
                    UpdatePin(m_lastFocusedElement, false /* addPin */);
                }

                if (focusedElement != null)
                {
                    UpdatePin(focusedElement, true /* addPin */);
                }

                m_lastFocusedElement = (focusedElement);
            }
        }
Пример #4
0
        protected override Size ArrangeOverride(Size finalSize)
        {
            if (m_isLayoutInProgress)
            {
                throw new Exception("Reentrancy detected during layout.");
            }

            if (IsProcessingCollectionChange)
            {
                throw new Exception("Cannot run layout in the middle of a collection change.");
            }

            m_isLayoutInProgress = true;
            try
            {
                Size arrangeSize = default;

                if (Layout is Layout layout)
                {
                    arrangeSize = layout.Arrange(GetLayoutContext(), finalSize);
                }

                // The view manager might clear elements during this call.
                // That's why we call it before arranging cleared elements
                // off screen.
                ViewManager.OnOwnerArranged();

                var children = Children;
                for (int i = 0; i < children.Count; ++i)
                {
                    var element  = children[i];
                    var virtInfo = GetVirtualizationInfo(element);
                    virtInfo.KeepAlive = false;

                    if (virtInfo.Owner == ElementOwner.ElementFactory ||
                        virtInfo.Owner == ElementOwner.PinnedPool)
                    {
                        // Toss it away. And arrange it with size 0 so that XYFocus won't use it.
                        element.Arrange(new Rect(
                                            ClearedElementsArrangePosition.X - element.DesiredSize.Width,
                                            ClearedElementsArrangePosition.Y - element.DesiredSize.Height,
                                            0.0,
                                            0.0));
                    }
                    else
                    {
                        var newBounds = CachedVisualTreeHelpers.GetLayoutSlot(element as FrameworkElement);

                        if (virtInfo.ArrangeBounds != InvalidRect &&
                            newBounds != virtInfo.ArrangeBounds)
                        {
                            AnimationManager.OnElementBoundsChanged(element, virtInfo.ArrangeBounds, newBounds);
                        }

                        virtInfo.ArrangeBounds = newBounds;
                    }
                }

                m_viewportManager.OnOwnerArranged();
                AnimationManager.OnOwnerArranged();

                return(arrangeSize);
            }
            finally
            {
                m_isLayoutInProgress = false;
            }
        }
Пример #5
0
        private UIElement GetElementFromElementFactory(int index)
        {
            // The view generator is the provider of last resort.
            var data = m_owner.ItemsSourceView.GetAt(index);

            UIElement initElement()
            {
                var providedElementFactory = m_owner.ItemTemplateShim;

                if (providedElementFactory == null)
                {
                    if (data is UIElement dataAsElement)
                    {
                        return(dataAsElement);
                    }
                }

                IElementFactoryShim initElementFactory()
                {
                    if (providedElementFactory == null)
                    {
                        var factory = XamlReader.Parse("<DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'><TextBlock Text='{Binding}'/></DataTemplate>") as DataTemplate;
                        m_owner.ItemTemplate = factory;
                        return(m_owner.ItemTemplateShim);
                    }
                    return(providedElementFactory);
                }

                var elementFactory = initElementFactory();

                ElementFactoryGetArgs initArgs()
                {
                    if (m_ElementFactoryGetArgs == null)
                    {
                        m_ElementFactoryGetArgs = new ElementFactoryGetArgs();
                    }
                    return(m_ElementFactoryGetArgs);
                }

                var args = initArgs();

                try
                {
                    args.Data   = data;
                    args.Parent = m_owner;
                    args.Index  = index;

                    return(elementFactory.GetElement(args));
                }
                finally
                {
                    args.Data   = null;
                    args.Parent = null;
                }
            }

            var element = initElement();

            var virtInfo = ItemsRepeater.TryGetVirtualizationInfo(element);

            if (virtInfo == null)
            {
                virtInfo = ItemsRepeater.CreateAndInitializeVirtualizationInfo(element);
            }
            else
            {
                // View obtained from ElementFactory already has a VirtualizationInfo attached to it
                // which means that the element has been recycled and not created from scratch.
            }

            if (data != element)
            {
                if (element is FrameworkElement elementAsFE)
                {
                    // Set data context only if no x:Bind was used. ie. No data template component on the root.
                    // If the passed in data is a UIElement and is different from the element returned by
                    // the template factory then we need to propagate the DataContext.
                    // Otherwise just set the DataContext on the element as the data.
                    object initElementDataContext()
                    {
                        if (data is FrameworkElement dataAsElement)
                        {
                            var dataDataContext = dataAsElement.DataContext;
                            if (dataDataContext != null)
                            {
                                return(dataDataContext);
                            }
                        }
                        return(data);
                    }

                    var elementDataContext = initElementDataContext();

                    elementAsFE.DataContext = elementDataContext;
                }
                else
                {
                    Debug.Assert(false, "Element returned by factory is not a FrameworkElement!");
                }
            }

            virtInfo.MoveOwnershipToLayoutFromElementFactory(
                index,
                /* uniqueId: */
                m_owner.ItemsSourceView.HasKeyIndexMapping ?
                m_owner.ItemsSourceView.KeyFromIndex(index) :
                string.Empty);

            // The view generator is the only provider that prepares the element.
            var repeater = m_owner;

            // Add the element to the children collection here before raising OnElementPrepared so
            // that handlers can walk up the tree in case they want to find their IndexPath in the
            // nested case.
            var children = repeater.Children;

            if (CachedVisualTreeHelpers.GetParent(element) != repeater)
            {
                children.Add(element);
            }

            repeater.AnimationManager.OnElementPrepared(element);

            repeater.OnElementPrepared(element, index);

            // Update realized indices
            m_firstRealizedElementIndexHeldByLayout = Math.Min(m_firstRealizedElementIndexHeldByLayout, index);
            m_lastRealizedElementIndexHeldByLayout  = Math.Max(m_lastRealizedElementIndexHeldByLayout, index);

            return(element);
        }
Пример #6
0
        private UIElement GetElementFromElementFactory(int index)
        {
            // The view generator is the provider of last resort.
            var data = m_owner.ItemsSourceView.GetAt(index);

            var itemTemplateFactory = m_owner.ItemTemplateShim;

            UIElement element = null;
            bool      itemsSourceContainsElements = false;

            if (itemTemplateFactory == null)
            {
                element = data as UIElement;
                // No item template provided and ItemsSource contains objects derived from UIElement.
                // In this case, just use the data directly as elements.
                itemsSourceContainsElements = element != null;
            }

            if (element == null)
            {
                if (itemTemplateFactory == null)
                {
                    // If no ItemTemplate was provided, use a default
                    var factory = XamlReader.Parse("<DataTemplate xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'><TextBlock Text='{Binding}'/></DataTemplate>") as DataTemplate;
                    m_owner.ItemTemplate = factory;
                    itemTemplateFactory  = m_owner.ItemTemplateShim;
                }

                if (m_ElementFactoryGetArgs == null)
                {
                    // Create one.
                    m_ElementFactoryGetArgs = new ElementFactoryGetArgs();
                }

                var args = m_ElementFactoryGetArgs;
                args.Data   = data;
                args.Parent = m_owner;
                args.Index  = index;

                element = itemTemplateFactory.GetElement(args);

                args.Data   = null;
                args.Parent = null;
            }

            var virtInfo = ItemsRepeater.TryGetVirtualizationInfo(element);

            if (virtInfo == null)
            {
                virtInfo = ItemsRepeater.CreateAndInitializeVirtualizationInfo(element);
            }
            else
            {
                // View obtained from ElementFactory already has a VirtualizationInfo attached to it
                // which means that the element has been recycled and not created from scratch.
            }

            if (!itemsSourceContainsElements)
            {
                // Set data context only if no x:Bind was used. ie. No data template component on the root.
                var elementAsFE = element as FrameworkElement;
                elementAsFE.DataContext = data;
            }

            virtInfo.MoveOwnershipToLayoutFromElementFactory(
                index,
                /* uniqueId: */
                m_owner.ItemsSourceView.HasKeyIndexMapping ?
                m_owner.ItemsSourceView.KeyFromIndex(index) :
                string.Empty);

            // The view generator is the only provider that prepares the element.
            var repeater = m_owner;

            // Add the element to the children collection here before raising OnElementPrepared so
            // that handlers can walk up the tree in case they want to find their IndexPath in the
            // nested case.
            var children = repeater.Children;

            if (CachedVisualTreeHelpers.GetParent(element) != repeater)
            {
                children.Add(element);
            }

            repeater.AnimationManager.OnElementPrepared(element);

            repeater.OnElementPrepared(element, index);

            // Update realized indices
            m_firstRealizedElementIndexHeldByLayout = Math.Min(m_firstRealizedElementIndexHeldByLayout, index);
            m_lastRealizedElementIndexHeldByLayout  = Math.Max(m_lastRealizedElementIndexHeldByLayout, index);

            return(element);
        }