From 65bd5f4e8a6a534f7aab8fd265b5d02855fdbb15 Mon Sep 17 00:00:00 2001 From: Joshua Askharoun Date: Tue, 22 Feb 2022 14:32:20 -0600 Subject: [PATCH] Added entrance animation to home page --- .../Behaviors/FadeAnimateItemsBehavior.cs | 75 +++++++++++++++++++ ZuneModdingHelper/MainWindow.xaml | 10 +++ ZuneModdingHelper/MainWindow.xaml.cs | 7 +- 3 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 ZuneModdingHelper/Behaviors/FadeAnimateItemsBehavior.cs diff --git a/ZuneModdingHelper/Behaviors/FadeAnimateItemsBehavior.cs b/ZuneModdingHelper/Behaviors/FadeAnimateItemsBehavior.cs new file mode 100644 index 0000000..6163ba5 --- /dev/null +++ b/ZuneModdingHelper/Behaviors/FadeAnimateItemsBehavior.cs @@ -0,0 +1,75 @@ +using Microsoft.Xaml.Behaviors; +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using System.Windows.Controls; +using System.Windows.Media.Animation; +using System.Windows.Threading; + +namespace ZuneModdingHelper.Behaviors +{ + // https://stackoverflow.com/a/5910833 + public class FadeAnimateItemsBehavior : Behavior + { + public DoubleAnimation Animation { get; set; } + public TimeSpan Tick { get; set; } + + protected override void OnAttached() + { + base.OnAttached(); + AssociatedObject.Loaded += AssociatedObject_Loaded; + } + + void AssociatedObject_Loaded(object sender, System.Windows.RoutedEventArgs e) + { + IEnumerable items; + if (AssociatedObject.ItemsSource == null) + { + items = AssociatedObject.Items.Cast(); + } + else + { + var itemsSource = AssociatedObject.ItemsSource; + if (itemsSource is INotifyCollectionChanged) + { + var collection = itemsSource as INotifyCollectionChanged; + collection.CollectionChanged += (s, cce) => + { + if (cce.Action == NotifyCollectionChangedAction.Add) + { + var itemContainer = AssociatedObject.ItemContainerGenerator.ContainerFromItem(cce.NewItems[0]) as ListBoxItem; + itemContainer.BeginAnimation(ListBoxItem.OpacityProperty, Animation); + } + }; + + } + ListBoxItem[] itemsSub = new ListBoxItem[AssociatedObject.Items.Count]; + for (int i = 0; i < itemsSub.Length; i++) + { + itemsSub[i] = AssociatedObject.ItemContainerGenerator.ContainerFromIndex(i) as ListBoxItem; + } + items = itemsSub; + } + foreach (var item in items) + { + item.Opacity = 0; + } + var enumerator = items.GetEnumerator(); + if (enumerator.MoveNext()) + { + DispatcherTimer timer = new() { Interval = Tick }; + timer.Tick += (s, timerE) => + { + var item = enumerator.Current; + item.BeginAnimation(ListBoxItem.OpacityProperty, Animation); + if (!enumerator.MoveNext()) + { + timer.Stop(); + } + }; + timer.Start(); + } + } + } +} diff --git a/ZuneModdingHelper/MainWindow.xaml b/ZuneModdingHelper/MainWindow.xaml index 7b08b9b..b9c24f0 100644 --- a/ZuneModdingHelper/MainWindow.xaml +++ b/ZuneModdingHelper/MainWindow.xaml @@ -6,6 +6,8 @@ xmlns:local="clr-namespace:ZuneModdingHelper" xmlns:core="clr-namespace:ZuneModCore;assembly=ZuneModCore" xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro" + xmlns:i="http://schemas.microsoft.com/xaml/behaviors" + xmlns:b="clr-namespace:ZuneModdingHelper.Behaviors" mc:Ignorable="d" Title="{x:Static local:App.Title}" Height="450" Width="800" WindowStartupLocation="CenterScreen" Loaded="Window_Loaded"> @@ -131,6 +133,14 @@ + + + + + + + + diff --git a/ZuneModdingHelper/MainWindow.xaml.cs b/ZuneModdingHelper/MainWindow.xaml.cs index ddfaea3..800b929 100644 --- a/ZuneModdingHelper/MainWindow.xaml.cs +++ b/ZuneModdingHelper/MainWindow.xaml.cs @@ -34,20 +34,21 @@ namespace ZuneModdingHelper public MainWindow() { InitializeComponent(); + // https://github.com/Arlodotexe/OwlCore/issues/1 OwlCore.Threading.SetPrimarySynchronizationContext(System.Threading.SynchronizationContext.Current!); OwlCore.Threading.SetPrimaryThreadInvokeHandler(RunOnUI); ThemeManager.Current.ThemeSyncMode = ThemeSyncMode.SyncWithAppMode; ThemeManager.Current.SyncTheme(); + + ModList.ItemsSource = Mod.AvailableMods; + ZuneInstallDirBox.Text = Mod.ZuneInstallDir; } private async System.Threading.Tasks.Task RunOnUI(Action action) => await Dispatcher.BeginInvoke(action); private async void Window_Loaded(object sender, RoutedEventArgs e) { - ModList.ItemsSource = Mod.AvailableMods; - ZuneInstallDirBox.Text = Mod.ZuneInstallDir; - // Show a warning if Zune is running Process[] procs = Process.GetProcessesByName("Zune"); string zuneExePath = Path.Combine(Mod.ZuneInstallDir, "Zune.exe");