Skip to content

Commit

Permalink
Merge pull request #102 from atc-net/feature/AutoScrollListViewBehavior
Browse files Browse the repository at this point in the history
Feature/auto scroll list view behavior
  • Loading branch information
davidkallesen authored Feb 9, 2024
2 parents da0415e + dd3ae55 commit 9b4fd26
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 7 deletions.
35 changes: 35 additions & 0 deletions src/Atc.Wpf.Controls/Behaviors/AutoScrollListViewBehavior.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
namespace Atc.Wpf.Controls.Behaviors;

public class AutoScrollListViewBehavior : Behavior<ListView>
{
public bool ScrollToBottom { get; set; } = true;

protected override void OnAttached()
{
base.OnAttached();
var items = AssociatedObject.Items;
((INotifyCollectionChanged)items).CollectionChanged += OnCollectionChanged;
}

protected override void OnDetaching()
{
base.OnDetaching();
var items = AssociatedObject.Items;
((INotifyCollectionChanged)items).CollectionChanged -= OnCollectionChanged;
}

private void OnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
var listView = AssociatedObject;
if (listView.Items.Count <= 1)
{
return;
}

var targetItem = ScrollToBottom
? listView.Items[^1]!
: listView.Items[0]!;

listView.ScrollIntoView(targetItem);
}
}
3 changes: 2 additions & 1 deletion src/Atc.Wpf.Controls/GlobalUsings.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
global using System.Collections;
global using System.Collections.Specialized;
global using System.ComponentModel;
global using System.ComponentModel.DataAnnotations;
global using System.ComponentModel.Design.Serialization;
Expand Down Expand Up @@ -46,7 +47,6 @@
global using Atc.Wpf.Controls.Resources;
global using Atc.Wpf.Controls.Selectors;
global using Atc.Wpf.Helpers;
global using Atc.Wpf.Media;
global using Atc.Wpf.Messaging;
global using Atc.Wpf.Serialization.JsonConverters;
global using Atc.Wpf.Theming.Controls.Selectors;
Expand All @@ -57,5 +57,6 @@
global using ControlzEx.Theming;

global using Microsoft.Win32;
global using Microsoft.Xaml.Behaviors;

global using Newtonsoft.Json.Linq;
9 changes: 7 additions & 2 deletions src/Atc.Wpf.Controls/Notifications/ToastNotification.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,17 @@ public override void OnApplyTemplate()
closeButton.Click += OnCloseButtonOnClick;
}

var storyboards = Template.Triggers.OfType<EventTrigger>()
var storyboards = Template.Triggers.OfType<System.Windows.EventTrigger>()
.FirstOrDefault(x => x.RoutedEvent == NotificationCloseInvokedEvent)?.Actions.OfType<BeginStoryboard>()
.Select(a => a.Storyboard);

closingAnimationTime = new TimeSpan(
storyboards?.Max(x => System.Math.Min((x.Duration.HasTimeSpan ? x.Duration.TimeSpan + (x.BeginTime ?? TimeSpan.Zero) : TimeSpan.MaxValue).Ticks, x.Children.Select(ch => ch.Duration.TimeSpan + (x.BeginTime ?? TimeSpan.Zero)).Max().Ticks)) ?? 0);
storyboards?.Max(x =>
System.Math.Min(
(x.Duration.HasTimeSpan
? x.Duration.TimeSpan + (x.BeginTime ?? TimeSpan.Zero)
: TimeSpan.MaxValue).Ticks,
x.Children.Select(ch => ch.Duration.TimeSpan + (x.BeginTime ?? TimeSpan.Zero)).Max().Ticks)) ?? 0);
}

[SuppressMessage("AsyncUsage", "AsyncFixer03:Fire-and-forget async-void methods or delegates", Justification = "OK - Need 'async void' and not 'async Task'")]
Expand Down
1 change: 0 additions & 1 deletion src/Atc.Wpf.Theming/Behaviors/WindowsSettingBehavior.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// ReSharper disable ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract

namespace Atc.Wpf.Theming.Behaviors;

[SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "OK.")]
Expand Down
4 changes: 1 addition & 3 deletions src/Atc.Wpf.Theming/GlobalUsings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,4 @@
global using Windows.Win32.Foundation;
global using Windows.Win32.Graphics.Gdi;
global using Windows.Win32.UI.WindowsAndMessaging;
global using Atc.Helpers;
global using Atc.Wpf.Collections;
global using Atc.Wpf.Media;
global using Atc.Wpf.Collections;
10 changes: 10 additions & 0 deletions src/Atc.Wpf/Enums/SelectionMode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// ReSharper disable once CheckNamespace
namespace Atc.Wpf;

[SuppressMessage("Naming", "CA1720:Identifier contains type name", Justification = "OK.")]
public enum SelectionMode
{
None,
Single,
Multiple,
}
127 changes: 127 additions & 0 deletions src/Atc.Wpf/Helpers/KeyboardHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
namespace Atc.Wpf.Helpers;

public static class KeyboardHelper
{
public static bool IsKeyDownAlt()
=> Keyboard.IsKeyDown(Key.LeftAlt) ||
Keyboard.IsKeyDown(Key.RightAlt);

public static bool IsKeyDownCtrl()
=> Keyboard.IsKeyDown(Key.LeftCtrl) ||
Keyboard.IsKeyDown(Key.RightCtrl);

public static bool IsKeyDownShift()
=> Keyboard.IsKeyDown(Key.LeftShift) ||
Keyboard.IsKeyDown(Key.RightShift);

public static bool IsKeyDownCtrlOrShift()
=> IsKeyDownCtrl() ||
IsKeyDownShift();

public static bool IsKeyDownCtrlAndShift()
=> IsKeyDownCtrl() &&
IsKeyDownShift();

public static bool IsKeyDownAltAndShiftAndCtrl()
=> IsKeyDownAlt() &&
IsKeyDownShift() &&
IsKeyDownCtrl();

public static bool IsKeyDownArrow()
=> Keyboard.IsKeyDown(Key.Left) ||
Keyboard.IsKeyDown(Key.Up) ||
Keyboard.IsKeyDown(Key.Right) ||
Keyboard.IsKeyDown(Key.Down);

public static bool IsKeyDownRegularNumber()
=> Keyboard.IsKeyDown(Key.D0) ||
Keyboard.IsKeyDown(Key.D1) ||
Keyboard.IsKeyDown(Key.D2) ||
Keyboard.IsKeyDown(Key.D3) ||
Keyboard.IsKeyDown(Key.D4) ||
Keyboard.IsKeyDown(Key.D5) ||
Keyboard.IsKeyDown(Key.D6) ||
Keyboard.IsKeyDown(Key.D7) ||
Keyboard.IsKeyDown(Key.D8) ||
Keyboard.IsKeyDown(Key.D9);

public static bool IsKeyDownNumPadNumber()
=> Keyboard.IsKeyDown(Key.NumPad0) ||
Keyboard.IsKeyDown(Key.NumPad1) ||
Keyboard.IsKeyDown(Key.NumPad2) ||
Keyboard.IsKeyDown(Key.NumPad3) ||
Keyboard.IsKeyDown(Key.NumPad4) ||
Keyboard.IsKeyDown(Key.NumPad5) ||
Keyboard.IsKeyDown(Key.NumPad6) ||
Keyboard.IsKeyDown(Key.NumPad7) ||
Keyboard.IsKeyDown(Key.NumPad8) ||
Keyboard.IsKeyDown(Key.NumPad9);

public static bool IsKeyDownNumber()
=> IsKeyDownRegularNumber() ||
IsKeyDownNumPadNumber();

public static bool IsKeyRegularNumber(
Key key)
=> key is
Key.D0 or
Key.D1 or
Key.D2 or
Key.D3 or
Key.D4 or
Key.D5 or
Key.D6 or
Key.D7 or
Key.D8 or
Key.D9;

public static bool IsKeyNumPadNumber(
Key key)
=> key is
Key.NumPad0 or
Key.NumPad1 or
Key.NumPad2 or
Key.NumPad3 or
Key.NumPad4 or
Key.NumPad5 or
Key.NumPad6 or
Key.NumPad7 or
Key.NumPad8 or
Key.NumPad9;

public static bool IsKeyNumber(
Key key)
=> IsKeyRegularNumber(key) ||
IsKeyNumPadNumber(key);

public static bool IsKeyArrow(
Key key)
=> key is
Key.Left or
Key.Up or
Key.Right or
Key.Down;

public static ArrowDirectionType GetArrowDirectionTypeFromKeyDown()
{
var direction = ArrowDirectionType.None;
if (Keyboard.IsKeyDown(Key.Left))
{
direction = ArrowDirectionType.Left;
}
else if (Keyboard.IsKeyDown(Key.Up))
{
direction = ArrowDirectionType.Up;
}
else if (Keyboard.IsKeyDown(Key.Right))
{
direction = ArrowDirectionType.Right;
}
else if (Keyboard.IsKeyDown(Key.Down))
{
direction = ArrowDirectionType.Down;
}

return direction;
}
}

0 comments on commit 9b4fd26

Please sign in to comment.