Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Property panel for ViewportBehavior #4320

Merged
merged 5 commits into from
Oct 15, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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="@[IsAlwaysOn:Bool:True]" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe rather than a toggle we just want this to be on by default (for the sample)?

</interactivity:Interaction.Behaviors>
<Image x:Name="EffectElement"
Width="100"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
using System;
michael-hawker marked this conversation as resolved.
Show resolved Hide resolved
using Windows.UI.Xaml;

namespace Microsoft.Toolkit.Uwp.UI.Behaviors
{
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 =
michael-hawker marked this conversation as resolved.
Show resolved Hide resolved
DependencyProperty.Register(nameof(IsAlwaysOn), typeof(bool), typeof(ViewportBehavior), new PropertyMetadata(true));

/// <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 (obj.IsAlwaysOn)
{
if (value)
{
obj.EnteredViewport?.Invoke(obj.AssociatedObject, EventArgs.Empty);
}
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 (obj.IsAlwaysOn)
{
if (value)
{
obj.EnteringViewport?.Invoke(obj.AssociatedObject, EventArgs.Empty);
}
else
{
obj.ExitedViewport?.Invoke(obj.AssociatedObject, EventArgs.Empty);
}
}
}
}
}
80 changes: 1 addition & 79 deletions Microsoft.Toolkit.Uwp.UI.Behaviors/Viewport/ViewportBehavior.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,13 @@ namespace Microsoft.Toolkit.Uwp.UI.Behaviors
/// <summary>
/// A class for listening 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)
michael-hawker marked this conversation as resolved.
Show resolved Hide resolved
{
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