UWP için MVVM destekli Modal Dialog Helper.

UWP uygulamaları geliştirirken çok sorunla karşılaştığım ve uzunca bir süredir canımı sıkan bir konu var. ContentDialog. Oldukça hoş bir görüntüsü olduğunu söyleyebilirim. Kullanıcıdan cevap almak için birebir. FAKAT AŞIRI SINIRLI!

Evet çok sınırlı bir kontrol. Sınırlı kontrolden kastım özelleştirmesi oldukça zahmetli ve hatta bazı şeyleri yapabilmek için imkansız bir kontrol. Ben dahil bir çok geliştiricinin tam ekran kaplayan bir ContentDialog tasarlarken kafayı yediğini öngörebiliyorum. Hayır bahsettiğim FullSizeDesired değil…

Microsoft’un bu konudaki tutuculuğunu anlayabiliyorum. Bir amaç uğruna tasarlanmış bir kontrolün amacı dışında kullanılmasını engellemek oldukça mantıklı bir davranış. Bir modal dialog olarak ContentDialog altyapısını kullanmak ilk başta oldukça mantıklı gelse de biraz haşır neşir olunduktan sonra imkansız olduğunu anlayabiliyoruz. WinRT zamanlarında kullandığımız modal dialog açmamıza yarayan helper classların çoğunun yeni UWP altyapısında çalışmadığını görmek beni ilk başta üzmüş olsa da kendiminkini yazmak için cesaretlendirdi.

Tıpkı bir ContentDialog gibi çalışan, kolayca özelleştirilebilir ve MVVM altyapısına uygun bir ModalDialogHelper sınıfı hazırladım. Bu generic sınıfın özelliği parametre olarak verdiğiniz herhangi bir Control objesini ContentDialog gibi bir container elementinin içine basması ve async bir şekilde kapatılmasını beklemesi. Eğer ViewModel tarafından aktarmak istediğiniz bir sonuç varsa bu bekleme işlemi sırasında onu da yakalayabilmenize imkan sağlıyor. Yani:

var result = await (new ModalDialogHelper<bool>()).ShowDialogAsync(typeof(TestUserControl),new TestUserControlViewModel());

tarzındaki bir kullanım DataContext’i TestUserControlViewModel olan bir TestUserControl kontrolünü ekrana basıp ViewModel içerisinden diyaloğu kapatmak istediğiniz bir methoddaki cevabı bekler.

Kendi amacım için olan kısmında bu datacontext mevzusu tamamen yoktu çünkü projemde Unity container olduğu için viewmodel bağlantıları otomatik olarak oluşturuluyordu. Fakat paylaşmak adına bu şekilde bir kullanım da ekledim.

Diyaloğu ViewModel içerisinden kapatmak için :

DialogDismissRequested.Invoke(null, null);

DialogDismissRequested eventini çağırmanız yeterli. Bu eventin ikinci parametresi T generic alıyor ve geriye döndürmek istediğiniz cevabın türünden olmak zorunda. Yukarıdaki örnekte ModalDialogHelper<bool> kullanimindaki bool aslında döndürmek istediğim tür olduğu için bu şekilde örnekledim.

Yukarıda yazıya başlarken bir containerdan bahsetmiştim. Unity olmayan ModalDialogContainer. Bu container da aslında bir Control ve kendine ait bir ContentTemplate içeren bir XAML resource’u içeriyor :

<Style TargetType="local:ModalDialogContainer">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="local:ModalDialogContainer">
                        <Grid>
                            <Grid Background="Black" Opacity="0.8"/>
                            <ContentPresenter x:Name="ContentPresenter" Margin="16">
                                <ContentPresenter.Transitions>
                                    <TransitionCollection>
                                        <EntranceThemeTransition />
                                    </TransitionCollection>
                                </ContentPresenter.Transitions>
                            </ContentPresenter>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

Ben ContentDialog görünümü verebilmek için arkaya %80 opacity kullandım. Aşağıdaki resimde gördüğünüz kontrol TestUserControl ve yukarıdaki satırları kullanarak ekrana bastığınız Modal şu şekilde görülüyor :

testusercontrolpreview

Arkaplanda beyazdan kırmızıya giden bir grandient Grid mevcut.

ModalDialogHelper’ın işi UI ile olduğu için sanırım yapılan bütün çağrıların UI Thread üzerinden yapılması gerektiğinden bahsetmeme gerek yok 🙂

Bu helper özelleştirilebilir. Normal ContentDialogda aşina olduğumuz geri tuşuna basıldığında diyaloğu kapatma gibi özellikler eklenebilir. Fakat şimdilik başlangıç için yeterli diye düşünüyorum.

ModalDialogHelper’ı kullanırken hatırlamanız gereken şeyler :

  • ViewModel her zaman IModalDialog interface’inden türemeli.
  • ShowDialogAsync methodu her zaman UI thread üzerinden çağırılmalı.
  • ViewModel içerisinde açılışta bir yükleme yapmak istiyorsanız OnInitializedAsync Task’ını kullanabilirsiniz.
  • Diyaloğu kapatmak veya beklediğiniz yanıtı göndermek için ViewModel içerisinden DialogDismissRequested eventini kullanabilirsiniz.

Helper’a ve örnek projeye buraya tıklayarak ulaşabileceğiniz GitHub reposu üzerinden ulaşabilirsiniz.

Cheers.

0
Shares