// Apply two sourcemodifiers to the input source: One to provide resistance, one to stop motion
        public void SetupPullToRefreshBehavior(
            float pullToRefreshDistance)
        {
            //
            // Modifier 1: Cut DeltaY to a third as long as the InteractionTracker is not yet at the
            // pullRefreshDistance.
            //

            CompositionConditionalValue resistanceModifier = CompositionConditionalValue.Create(_compositor);

            ExpressionAnimation resistanceCondition = _compositor.CreateExpressionAnimation(
                $"-tracker.Position.Y < {pullToRefreshDistance}");

            resistanceCondition.SetReferenceParameter("tracker", _tracker);

            ExpressionAnimation resistanceAlternateValue = _compositor.CreateExpressionAnimation(
                "source.DeltaPosition.Y / 3");

            resistanceAlternateValue.SetReferenceParameter("source", _interactionSource);

            resistanceModifier.Condition = resistanceCondition;
            resistanceModifier.Value     = resistanceAlternateValue;

            //
            // Modifier 2: Zero the delta if we are past the pullRefreshDistance. (So we can't pan
            // past the pullRefreshDistance)
            //

            CompositionConditionalValue stoppingModifier  = CompositionConditionalValue.Create(_compositor);
            ExpressionAnimation         stoppingCondition = _compositor.CreateExpressionAnimation(
                $"-tracker.Position.Y >= {pullToRefreshDistance}");

            stoppingCondition.SetReferenceParameter("tracker", _tracker);

            ExpressionAnimation stoppingAlternateValue = _compositor.CreateExpressionAnimation("0");

            stoppingModifier.Condition = stoppingCondition;
            stoppingModifier.Value     = stoppingAlternateValue;

            //
            // Apply the modifiers to the source as a list
            //

            List <CompositionConditionalValue> modifierList =
                new List <CompositionConditionalValue>()
            {
                resistanceModifier, stoppingModifier
            };

            _interactionSource.ConfigureDeltaPositionYModifiers(modifierList);
        }
        private void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            ThumbnailList.ItemsSource = new List <Item>
            {
                new Item {
                    Name = "Daren"
                },
                new Item {
                    Name = "Kendra"
                },
                new Item {
                    Name = "Gavin"
                },
                new Item {
                    Name = "Naia"
                },
                new Item {
                    Name = "Frodo"
                },
                new Item {
                    Name = "Stella"
                },
                new Item {
                    Name = "DJ"
                },
                new Item {
                    Name = "Stasch"
                }
            };

            // InteractionTracker and VisualInteractionSource setup.
            _root = ElementCompositionPreview.GetElementVisual(Root);
            _contentPanelVisual = ElementCompositionPreview.GetElementVisual(ContentPanel);
            _compositor         = _root.Compositor;
            _tracker            = InteractionTracker.Create(_compositor);
            _interactionSource  = VisualInteractionSource.Create(_root);
            _interactionSource.PositionYSourceMode   = InteractionSourceMode.EnabledWithInertia;
            _interactionSource.PositionYChainingMode = InteractionChainingMode.Always;
            _tracker.InteractionSources.Add(_interactionSource);
            var refreshPanelHeight = (float)RefreshPanel.ActualHeight;

            _tracker.MaxPosition = new Vector3((float)Root.ActualWidth, 0, 0);
            _tracker.MinPosition = new Vector3(-(float)Root.ActualWidth, -refreshPanelHeight, 0);

            // Use the Tacker's Position (negated) to apply to the Offset of the Image.
            // The -{refreshPanelHeight} is to hide the refresh panel
            m_positionExpression =
                _compositor.CreateExpressionAnimation($"-tracker.Position.Y - {refreshPanelHeight} ");
            m_positionExpression.SetReferenceParameter("tracker", _tracker);
            _contentPanelVisual.StartAnimation("Offset.Y", m_positionExpression);

            var resistanceModifier  = CompositionConditionalValue.Create(_compositor);
            var resistanceCondition = _compositor.CreateExpressionAnimation(
                $"-tracker.Position.Y < {pullToRefreshDistance}");

            resistanceCondition.SetReferenceParameter("tracker", _tracker);
            var resistanceAlternateValue = _compositor.CreateExpressionAnimation(
                "source.DeltaPosition.Y / 3");

            resistanceAlternateValue.SetReferenceParameter("source", _interactionSource);
            resistanceModifier.Condition = resistanceCondition;
            resistanceModifier.Value     = resistanceAlternateValue;

            var stoppingModifier  = CompositionConditionalValue.Create(_compositor);
            var stoppingCondition = _compositor.CreateExpressionAnimation(
                $"-tracker.Position.Y >= {pullToRefreshDistance}");

            stoppingCondition.SetReferenceParameter("tracker", _tracker);
            var stoppingAlternateValue = _compositor.CreateExpressionAnimation("0");

            stoppingModifier.Condition = stoppingCondition;
            stoppingModifier.Value     = stoppingAlternateValue;
            //Now add the 2 source modifiers to the InteractionTracker.
            var modifierList = new List <CompositionConditionalValue> {
                resistanceModifier, stoppingModifier
            };

            _interactionSource.ConfigureDeltaPositionYModifiers(modifierList);

            //The PointerPressed handler needs to be added using AddHandler method with the //handledEventsToo boolean set to "true"
            //instead of the XAML element's "PointerPressed=Window_PointerPressed",
            //because the list view needs to chain PointerPressed handled events as well.
            ContentPanel.AddHandler(PointerPressedEvent, new PointerEventHandler(Window_PointerPressed), true);
        }