Makale Özeti

Bu yazımıda Silverlight 3.0 ile beraber gelen ChildWindow nesnesinin hızlıca kullanımına göz atacağız.

Makale

Web uygulamalarında olsun Windows uygulamalarında olsun belki de en sık başvurduğumzu şey MessageBox'tır :) Sürekli bir yerlerde uyarılar gösterir ve en basit şekilde kullanıcıya bir mesaj iletmek için MessageBox yapısını kullanırız. Web ortamında da JavaScript alert imdadımıza yetişir. Peki ya Silverlight içerisinde?

"Silverlight içinde de MessageBox var!" dediğinizi duyar gibiyim :) ama MessageBox'ın biraz modası geçmedi mi artık? Şöyle daha güzel şeyler yapsak? Bir de üstüne yeri geldiğinde sadece bir mesaj değil de belki Web'deki PopUp'lar tadında farklı işlevsellikler içerebilen ekranlar da açmak istesek ne yapacağız? Tek tek UserControl'ler hazırlayıp sahnede uygun gerlerde göstermekle uğraşamayacak kadar basit bir işlevsellikten bahsediyoruz aslında. Tamam, daha fazla uzatmayacağım...

Karşınızda : "ChildWindow"!

Herhangi bir Silverlight projesine Solution Explorer içerisinde sağ tıklayarak "Add New Item" menüsüne geçtiğinizde karşınıza gelecek seçenekler arasına artık "Silverlight Child Window" da eklendi.

Yeni bir nesne tipi : Child Window
Yeni bir nesne tipi : Child Window

Silverlight içerisinde "UserControl" haricinde yapılara pek alışık değildik :) Silverlight 3.0 ile beraber karşımıza farklı şeyler çıkıyor. Bunlardan biri de System.Windows.Controls.dll'i altında bulunan ChildWindow nesnesi. Basit bir şekilde projenize bir ChildWindow eklediğinizde zaten ChildWindow'un otomatik olarak belirli standart bir tasarım ile geldiğini de göreceksiniz. Bu tasarım tabi ki Expression Blend ile açılıp değiştirilebilecek bir tasarım. Kontrolün XAML kısmına bakarsanız iki tane Button göreceksiniz, söz konusu buttonların Click durumlarında da arka planda ChildWindow'un DialogResult özelliği set ediliyor.

[VB]

    Private Sub OKButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles OKButton.Click

        Me.DialogResult = True

    End Sub

 

    Private Sub CancelButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles CancelButton.Click

        Me.DialogResult = False

    End Sub

[C#]

        private void OKButton_Click(object sender, RoutedEventArgs e)

        {

            this.DialogResult = true;

        }

 

        private void CancelButton_Click(object sender, RoutedEventArgs e)

        {

            this.DialogResult = false;

        }

Tahmin edeceğiniz üzere ChildWindow'un kullanımı epey kolay. ChildWindow'unuzu herhangi bir UserControl'den bir Instance'ını alarak Show metodu ile çağırabiliyor veya aynı şekilde Close metodu ile de uzaktan kapatabiliyorsunuz. Örneğin aşağıda gördüğünüz kod herhangi bir UserControl içerisinde biraz önce yarattığımız ChildWindow'u çağıran kodun ta kendisi.

[VB]

        Dim Yeni As New ChildWindow1

        Yeni.Show()

[C#]

            ChildWindow1 Yeni = new ChildWindow1();

            Yeni.Show();

Sanırım daha basit olamazdı. Tabi söz konusu ChildWindow'u çağırdıktan sonra kapandığından da haberdar olup hatta kapanmadan önce en son aldığı DialogResult değerin de elde etmek gerekir. Bunun için ChildWindow'un Closed event'ını yakalamanız yeterli olacaktır.

[VB]

   Private Sub MainPage_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded

        Dim Yeni As New ChildWindow1

        AddHandler Yeni.Closed, AddressOf yeni_Closed

        Yeni.Show()

    End Sub

 

    Private Sub yeni_Closed(ByVal sender As Object, ByVal e As System.EventArgs)

        Dim Sonuc As Boolean = CType(sender, ChildWindow1).DialogResult

    End Sub

[C#]

        void MainPage_Loaded(object sender, RoutedEventArgs e)

        {

            ChildWindow1 Yeni = new ChildWindow1();

            Yeni.Closed += new EventHandler(Yeni_Closed);

            Yeni.Show();

        }

 

        void Yeni_Closed(object sender, EventArgs e)

        {

            Nullable<Boolean> Sonuc = ((ChildWindow1)sender).DialogResult;

        }

ChildWindow'u Show etmeden önce Closed eventını bir event-listener'a bağlarsanız sonrasında ChildWindow kapatıldığında rahatlıkla durumdan haberdar olabilirsiniz. Closed event'ı çalıştırıldığı anda sender olarak gelen objeyi kendi ChildWindow'umuza cast ederek DialogResult özelliğini alabiliyoruz. Eğer "Bana sadece Boolean sonuç döndürnek yetmez" diyorsanız aslında çözüm basit. Kendi tanımladığınız ChildWindow'un arkasında sınıfta yeni Property'ler tanımlayabilir ve bunları istediğiniz tipte yaratabilirsiniz. Böylece Closed event'ına gelen sender da aslında sizin tanımladığınız nesne olacağı için istediğiniz Property'sine erişebilirsiniz. Eğer ChildWindow kapanmadan önce sizin tanımladığınız Property'ye bir bilgi aktarırsa bu bilginin rahatlıkla ana UserControl'e gelebileceği anlamına gelir.

ChildWindow karşınızda.
ChildWindow karşınızda.

Gelin hızlı ve teorik bir örnek yapalım. Hazırlayacağımız yeni ChildWindow bizden bir Integer parametre alsın. Bu parametreyi aldıktan sonra zaten ChildWindow kendi içerisinde istediğini yapar. İsterse kendi içine konabilecek bir TextBlock'a bile yazdırabilir. (Uyarı mesajı olabilirdi bu parametre) Ama biz farklı birşey yapacağız. ChildWindow'un OK düğmesine basıldığında kendisine daha önce verilen sayıyıyı ikiyle çarpıp geri verecek, Cancel düğmesine basılınca ise ikiye bölecek. Böylece yeni bir ChildWindow yaratırken nasıl parametre geçebileceğimizi ve söz konusu parametre üzerinde ChildWindow değişiklik yaptıktan sonra parametreyi nasıl geri alabileceğimizi görmüş oluruz.

[VB]

Partial Public Class ChildWindow1

    Inherits ChildWindow

 

    Public Sub New(ByVal deger As Integer)

        InitializeComponent()

        Me.Deger = deger

    End Sub

 

    Private PDeger As Integer

    Public Property Deger() As Integer

        Get

            Return PDeger

        End Get

        Set(ByVal value As Integer)

            PDeger = value

        End Set

    End Property

 

    Private Sub OKButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles OKButton.Click

        Me.Deger *= 2

        Me.DialogResult = True

    End Sub

 

    Private Sub CancelButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles CancelButton.Click

        Me.Deger /= 2

        Me.DialogResult = False

    End Sub

 

End Class

[C#]

namespace SilverlightApplication5

{

    public partial class ChildWindow1 : ChildWindow

    {

        public ChildWindow1(int deger)

        {

            InitializeComponent();

            this.Deger = deger;

        }

 

        public int Deger { get; set; }

 

        private void OKButton_Click(object sender, RoutedEventArgs e)

        {

            this.Deger = this.Deger * 2;

            this.DialogResult = true;

        }

 

        private void CancelButton_Click(object sender, RoutedEventArgs e)

        {

            this.Deger = this.Deger / 2;

            this.DialogResult = false;

        }

    }

}

Yukarıda kalın yazılı olarak gördüğünüz yerler bizim eklememiz gereken satırlar. Hemen ChildWindow'umuzun Constructor'ı ile işe başlayalım. Artık elimizdeki Constructor bir parametre istiyor. Bu parametre ChildWindow'a aktarılacak olan veriyi temsil edecek. Bizim örneğimizde Integer olabilir fakat siz farklı nesne tiplerini ve hatta kendi tanımladığınız nesne tiplerini de parametre olarak geçebilirsiniz. Sonrasında söz konusu parametreyle gelen değişkeni elde saklayabilmek için bir de Property tanımlıyoruz, hatta constructor çalıştığında da kendisine gelen veriyi Property'e atamasını sağlıyoruz.

Artık verimizi rahat rahat elimize aldığımıza göre Ok ve Cancel düğmelerinde söz konusu veriyi istediğimiz gibi değiştirebiliriz. Farklı senaryolarda ChildWindow içerisinde koyduğunuz farklı kontrollerden gelen verilere göre bu şekilde farklı Property'leri değiştirebilirsiniz. Peki söz konusu ChildWindow'u çalıştıran UserControl buradaki Property'ye nasıl ulaşacak? Aslında çok kolay.

[VB]

    Private Sub yeni_Closed(ByVal sender As Object, ByVal e As System.EventArgs) Handles yeni.Closed

        Dim Sonuc = CType(sender, ChildWindow1).Deger

    End Sub

[C#]

        void Yeni_Closed(object sender, EventArgs e)

        {

            int Sonuc = ((ChildWindow1)sender).Deger;

        }

Gördüğünüz gibi ChildWindow kapandıktan sonra nasıl DialogResult değerini aldıysak aynı şekilde kendi tanımladığımız Property'lere de ulaşabiliyoruz. Ne de olsa sender'ı kendi tanımladığımız ChildWindow1 sınıfına cast ediyoruz. İşte bir ChildWindow'a parametre gönderip farklı veriler alabilmek bu kadar kolay.

Hmm iyiymiş...

Kesinlikle muhteşem! İster özel Property'ler tanımlayın ister ChildWindow'un constructor'larını değiştirip farklı bilgiler atayarak onları göstermesini sağlayın ChildWindow'lar kullanım açısından çok pratik ve şık. Otomatik olarak kendi kendileri ekranın geri kalanını yarı şeffaf bir perde ile kapatıp kullanılamaz hale getirmeler ve hoş bir animasyon ile ekrana gelip gitmeleri gerçekten iş uygulamalarında genel kullanıma çok uygun. Fakat tabi ki özel durumlarda, kullanıcı deneyiminin ve tasarımın daha öne çıktığı senaryolarda kesinlikle ChildWindow'ların özelleştirilmesi gerekiyor.

Aklıma gelmişken :) Ben bir projede ChildWindow'ları sadece Loading animasyonları göstermek için kullandım. Gerçekten pratik oluyor. Loading mesajını verirken istediğimiz şey zaten kullanıcının başka birşey yapamaması. Tabi bu amaçla yaratılan bir ChildWindow'un Close vs gibi düğmelerinin tasarımdan Blend aracılığı ile kaldırılması gerekiyor. Arka planda yükleme işlemi bittiğinde siz ChildWindow'un Close metodu ile pencereyi ekrandan kaldırabiliyorsunuz. Eh pencerenin için de bir de Indeterminate state'te ProgressBar varsa zaten yeme de yanında yat :)

Hepinize kolay gelsin...