public static void MarqueeAsync(this FrameworkElement element, float seconds = 3f) { var sb = new Storyboard(); var unloaded = false; element.Unloaded += (s, e) => unloaded = true; CoreDi.TaskManager.Run(async() => { while (element != null && !unloaded) { double width; double innerWidth; try { if (element == null || unloaded) { break; } width = element.ActualWidth; innerWidth = ((FrameworkElement)((Border)element).Child).ActualWidth; } catch { break; } Application.Current.Dispatcher.Invoke(() => { sb.AddMarquee(seconds, width, innerWidth); sb.Begin(element); element.Visibility = Visibility.Visible; }); await Task.Delay((int)seconds * 1000); if (seconds == 0) { break; } } }); }
/// <summary> /// Animates a marquee style element /// The structure should be: /// [Border ClipToBounds="True"] /// [Border local:AnimateMarqueeProperty.Value="True"] /// [Content HorizontalAlignment="Left"] /// [/Border] /// [/Border] /// </summary> /// <param name="element">The element to animate</param> /// <param name="seconds">The time the animation will take</param> /// <returns></returns> public static void MarqueeAsync(this FrameworkElement element, float seconds = 3f) { // Create the storyboard var sb = new Storyboard(); // Run until element is unloaded var unloaded = false; // Monitor for element unloading element.Unloaded += (s, e) => unloaded = true; // Run a loop off the caller thread Task.Run(async() => { // While the element is still available, recheck the size // after every loop in case the container was resized while (element != null && !unloaded) { // Create width variables var width = 0d; var innerWidth = 0d; try { // Check if element is still loaded if (element == null || unloaded) { break; } // Try and get current width width = element.ActualWidth; innerWidth = ((element as Border).Child as FrameworkElement).ActualWidth; } catch { // Any issues then stop animating (presume element destroyed) break; } Application.Current.Dispatcher.Invoke(() => { // Add marquee animation sb.AddMarquee(seconds, width, innerWidth); // Start animating sb.Begin(element); // Make page visible element.Visibility = Visibility.Visible; }); // Wait for it to finish animating await Task.Delay((int)seconds * 1000); // If this is from first load or zero seconds of animation, do not repeat if (seconds == 0) { break; } } }); }