[UWP] Async Storyboard çağırmak.

Windows uygulamaları geliştirirken sayfadaki elementler üzerinde animasyon kullanmak istiyorsak Storyboardları kullanıyoruz. Genellikle geliştiriciler bu animasyonları hazırlamak için Blend kullanırlar. (Düzenlemek istediğiniz elementin bulunduğu sayfanın üzerine Solution Explorer’dan sağ tıklayarak ‘Design in Blend’ seçeneğine basarak erişebilirsiniz.)

Animasyonu oluşturup Storyboardumuzu XAML tarafında tanımladıktan sonra kod tarafında bu animasyonu belirlenen obje üzerinde oynatmak için Begin methodunu kullanıyoruz. Begin methodu senkron çalışan bir method ve Storyboard sınıfının içerisinde bu methodu asenkron hale getirecek başka bir oynatmak methodu bulunmuyor. Fakat Completed eventini ve TaskCompletionSource sınıfını kullanarak bütün Storyboardları asenkron çalıştıran bir extension method yazabiliriz.

sampleAnimation isimli bir Storyboard düşünelim. Bu animasyon başlamadan önce ekrana animasyonun çıkan diyalog kapatıldıktan sonra başlayacağını belirten bir mesaj verdirtelim. Daha sonra animasyonu oynatalım ve animasyonun bittiğine dair bir mesaj daha verdirelim.

private async void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    await (new MessageDialog("Animasyon bu diyalog kapatıldığında başlayacak.").ShowAsync());
    sampleAnimation.Begin();
    await (new MessageDialog("Animasyon bitti!").ShowAsync());
}

Peki ya bu animasyon bitmeden kodun devamına geçmesini istemiyorsak? Şu anki haliyle ilk diyalogu kapattığımız gibi animasyon başlayacak fakat Begin methodu senkron çalıştığı için kod çalıştırması devam edecek ve animasyonun bittiğini belirten ikinci bir diyalog gelecek. Animasyon 3,5 milisaniyede bitmiyorsa bu durumda çok yanlış yapıyoruz demektir 🙂 İşte o zaman bu oynatma methodunun asenkron haline ihtiyacımız oluyor. Aşağıdaki şekilde bir StoryboardHelper içerisinde BeginAsync extension methodunu yazarak bu işten kurtulabiliriz.

public static class StoryboardHelper
{
    public static Task BeginAsync(this Storyboard storyboard)
    {
        var completionSource = new TaskCompletionSource<object>();

        storyboard.Completed += (c, r) =>
        {
            completionSource.SetResult(null);
        };

        storyboard.Begin();

        return completionSource.Task;
    }
}

Daha sonra animasyonu oynattığımız yeri de aşağıdaki gibi düzenlersek amacımıza ulaşmış oluyoruz.

private async void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    await (new MessageDialog("Animasyon bu diyalog kapatıldığında başlayacak.").ShowAsync());
    await sampleAnimation.BeginAsync();
    await (new MessageDialog("Animasyon bitti!").ShowAsync());
}

Asenkron Storyboard kullanımına ihtiyacınız varsa TaskCompletionSource kullanımına ait de çok güzel bir örnek olan yukarıdaki BeginAsync methodunu kullanabilirsiniz.

0
Shares