Skip to content

Commit

Permalink
Merge pull request #4320 from XAML-Knight/dev/ViewportLogging
Browse files Browse the repository at this point in the history
Add Property panel for ViewportBehavior
  • Loading branch information
michael-hawker authored Oct 15, 2021
2 parents 72ab567 + 74021fb commit 3381011
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
Height="200"
Background="Gray">
<interactivity:Interaction.Behaviors>
<behaviors:ViewportBehavior x:Name="ViewportBehavior" />
<behaviors:ViewportBehavior x:Name="ViewportBehavior" IsAlwaysOn="True" />
</interactivity:Interaction.Behaviors>
<Image x:Name="EffectElement"
Width="100"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using Microsoft.Xaml.Interactivity;
using Windows.UI.Xaml;

namespace Microsoft.Toolkit.Uwp.UI.Behaviors
{
/// <summary>
/// A class for listening to an element enter or exit the ScrollViewer viewport
/// </summary>
public partial class ViewportBehavior
{
/// <summary>
/// The IsFullyInViewport value of the associated element
/// </summary>
public static readonly DependencyProperty IsFullyInViewportProperty =
DependencyProperty.Register(nameof(IsFullyInViewport), typeof(bool), typeof(ViewportBehavior), new PropertyMetadata(default(bool), OnIsFullyInViewportChanged));

/// <summary>
/// The IsInViewport value of the associated element
/// </summary>
public static readonly DependencyProperty IsInViewportProperty =
DependencyProperty.Register(nameof(IsInViewport), typeof(bool), typeof(ViewportBehavior), new PropertyMetadata(default(bool), OnIsInViewportChanged));

/// <summary>
/// The IsAlwaysOn value of the associated element
/// </summary>
public static readonly DependencyProperty IsAlwaysOnProperty =
DependencyProperty.Register(nameof(IsAlwaysOn), typeof(bool), typeof(ViewportBehavior), new PropertyMetadata(default(bool)));

/// <summary>
/// Gets or sets a value indicating whether this behavior will remain attached after the associated element enters the viewport. When false, the behavior will remove itself after entering.
/// </summary>
public bool IsAlwaysOn
{
get { return (bool)GetValue(IsAlwaysOnProperty); }
set { SetValue(IsAlwaysOnProperty, value); }
}

/// <summary>
/// Gets a value indicating whether associated element is fully in the ScrollViewer viewport
/// </summary>
public bool IsFullyInViewport
{
get { return (bool)GetValue(IsFullyInViewportProperty); }
private set { SetValue(IsFullyInViewportProperty, value); }
}

/// <summary>
/// Gets a value indicating whether associated element is in the ScrollViewer viewport
/// </summary>
public bool IsInViewport
{
get { return (bool)GetValue(IsInViewportProperty); }
private set { SetValue(IsInViewportProperty, value); }
}

/// <summary>
/// Event tracking when the object is fully within the viewport or not
/// </summary>
/// <param name="d">DependencyObject</param>
/// <param name="e">EventArgs</param>
private static void OnIsFullyInViewportChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var obj = (ViewportBehavior)d;
var value = (bool)e.NewValue;

if (value)
{
obj.EnteredViewport?.Invoke(obj.AssociatedObject, EventArgs.Empty);

if (!obj.IsAlwaysOn)
{
Interaction.GetBehaviors(obj.AssociatedObject).Remove(obj);
}
}
else
{
obj.ExitingViewport?.Invoke(obj.AssociatedObject, EventArgs.Empty);
}
}

/// <summary>
/// Event tracking the state of the object as it moves into and out of the viewport
/// </summary>
/// <param name="d">DependencyObject</param>
/// <param name="e">EventArgs</param>
private static void OnIsInViewportChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var obj = (ViewportBehavior)d;
var value = (bool)e.NewValue;

if (value)
{
obj.EnteringViewport?.Invoke(obj.AssociatedObject, EventArgs.Empty);
}
else
{
obj.ExitedViewport?.Invoke(obj.AssociatedObject, EventArgs.Empty);
}
}
}
}
82 changes: 2 additions & 80 deletions Microsoft.Toolkit.Uwp.UI.Behaviors/Viewport/ViewportBehavior.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,15 @@
namespace Microsoft.Toolkit.Uwp.UI.Behaviors
{
/// <summary>
/// A class for listening element enter or exit the ScrollViewer viewport
/// A class for listening to an element enter or exit the ScrollViewer viewport
/// </summary>
public class ViewportBehavior : BehaviorBase<FrameworkElement>
public partial class ViewportBehavior : BehaviorBase<FrameworkElement>
{
/// <summary>
/// The ScrollViewer hosting this element.
/// </summary>
private ScrollViewer _hostScrollViewer;

/// <summary>
/// The IsFullyInViewport value of the associated element
/// </summary>
public static readonly DependencyProperty IsFullyInViewportProperty =
DependencyProperty.Register(nameof(IsFullyInViewport), typeof(bool), typeof(ViewportBehavior), new PropertyMetadata(default(bool), OnIsFullyInViewportChanged));

/// <summary>
/// The IsInViewport value of the associated element
/// </summary>
public static readonly DependencyProperty IsInViewportProperty =
DependencyProperty.Register(nameof(IsInViewport), typeof(bool), typeof(ViewportBehavior), new PropertyMetadata(default(bool), OnIsInViewportChanged));

/// <summary>
/// The IsAlwaysOn value of the associated element
/// </summary>
public static readonly DependencyProperty IsAlwaysOnProperty =
DependencyProperty.Register(nameof(IsAlwaysOn), typeof(bool), typeof(ViewportBehavior), new PropertyMetadata(default(bool)));

/// <summary>
/// Associated element fully enter the ScrollViewer viewport event
/// </summary>
Expand All @@ -59,33 +41,6 @@ public class ViewportBehavior : BehaviorBase<FrameworkElement>
/// </summary>
public event EventHandler ExitingViewport;

/// <summary>
/// Gets or sets a value indicating whether this behavior will remain attached after the associated element enters the viewport. When false, the behavior will remove itself after entering.
/// </summary>
public bool IsAlwaysOn
{
get { return (bool)GetValue(IsAlwaysOnProperty); }
set { SetValue(IsAlwaysOnProperty, value); }
}

/// <summary>
/// Gets a value indicating whether associated element is fully in the ScrollViewer viewport
/// </summary>
public bool IsFullyInViewport
{
get { return (bool)GetValue(IsFullyInViewportProperty); }
private set { SetValue(IsFullyInViewportProperty, value); }
}

/// <summary>
/// Gets a value indicating whether associated element is in the ScrollViewer viewport
/// </summary>
public bool IsInViewport
{
get { return (bool)GetValue(IsInViewportProperty); }
private set { SetValue(IsInViewportProperty, value); }
}

/// <summary>
/// Called after the behavior is attached to the <see cref="P:Microsoft.Xaml.Interactivity.Behavior.AssociatedObject" />.
/// </summary>
Expand Down Expand Up @@ -120,39 +75,6 @@ protected override void OnDetaching()
_hostScrollViewer = null;
}

private static void OnIsFullyInViewportChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var obj = (ViewportBehavior)d;
var value = (bool)e.NewValue;
if (value)
{
obj.EnteredViewport?.Invoke(obj.AssociatedObject, EventArgs.Empty);

if (!obj.IsAlwaysOn)
{
Interaction.GetBehaviors(obj.AssociatedObject).Remove(obj);
}
}
else
{
obj.ExitingViewport?.Invoke(obj.AssociatedObject, EventArgs.Empty);
}
}

private static void OnIsInViewportChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var obj = (ViewportBehavior)d;
var value = (bool)e.NewValue;
if (value)
{
obj.EnteringViewport?.Invoke(obj.AssociatedObject, EventArgs.Empty);
}
else
{
obj.ExitedViewport?.Invoke(obj.AssociatedObject, EventArgs.Empty);
}
}

private void ParentScrollViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
var associatedElementRect = AssociatedObject.TransformToVisual(_hostScrollViewer)
Expand Down

0 comments on commit 3381011

Please sign in to comment.