Makale Özeti

Bu makalemizde özel Silverlight 2.0 kontrolleri yaratmanın yolunu inceliyoruz. Yazımızda Silverlight 2.0 ile beraber gelen standart Button kontrolünü baz alarak ek özelliklere sahip yeni bir Button kontrolü yaratıyoruz.

Makale

Silverlight 2.0 içerisinde kullandığımız standart kontrollerin yanı sıra istersek kendi kontrollerimizi de hazırlama şansımız var. Daha önceleri ister ASP.NET ister Windows uygulamalarından alışık olduğumuz bu uygulama ile hazırladığınız size özel kontrolleri farklı projelerde rahatlıkla kullanma şansına sahip olabilirsiniz. Bu yazımızda deneme amaçlı olarak Silverlight 2.0 ile beraber gelen Button kontrolünü baz alıp geliştirerek yeni bir kontrol oluşturacağız. Yaratacağımız yeni TimeOutButton kontrolü kullanıcından bir TimeOut değeri alacak. Milisaniye cinsinden verilen bu süre sonunda Button kullanılamaz hale gelecek. Bu esnada Button'un üzerinde sürekli kaç saniye kaldığı da yazılacak. Kullanıcıların belirli bir sürede bir işlemi tamamlamasını istiyorsanız bu gibi bir Button işinizi görebilir. Gelin hemen işe koyulalım.

Çalışma ortamımızı hazırlayalım.

Kontrolümüzü geliştirirken sürekli test etmek isteyeceğiz. O nedenle ilk olarak sağlıklı bir çalışma ortamı hazırlamamız lazım. Yeni bir Silverlight projesi yarattığınızda Visual Studio içerisinde Solution içinde bir ASP.NET ve bir de Silverlight projeniz bulunur. Solution dosyasına bir proje daha ekleyeceğiz. Solution Explorer içerisinde solution dosyasına sağ tuş ile tıkladıktan sonra "Add / New Project" diyerek "Silverlight Class Library" seçeneğini işaretlemeniz yeterli olacaktır. Böylece yeni kontrolümüzü oluşturmak için kodlarımızı yazacağımız ortamı geliştirdik.

Solution'ı Compile ettiğimizde Silverlight projemize otomatik olarak bu kontrol projemizin de eklenmesi gerekiyor. O nedenle hemen Silverlight projesine sağ tuş ile tıklayarak gelen menüden "Add Reference" komutunu verin ve karşınıza gelen pencereden de "Projects" tabına geçerek Class Library projenizi seçin. Böylece artık F5'e bastığınızda her şey otomatik olarak yapılacaktır ve kontrolünüzü kullanılır şekilde inceleyebileceksiniz. Tabi testlere geçmeden önce biraz kod yazmamız gerekiyor ;)

Kontrolümüzü hazırlayalım.

Class Library içerisinde kod dosyamızda düğmemizin adını taşıyan bir Class bulunuyor. Bu Class'ı biz örneğimizde standart Silverlight Button kontrolünden inherit edeceğiz. Böylece yeni ve gelişmiş bir Button yaratırken her şeye sıfırdan başlamayacağız, Silverlight içerisinde hazır Button kontrolünü alarak üzerine yeni işlevsellikler ekleyeceğiz.

[VB]

Public Class TimeOutButton

    Inherits Button

 

End Class

[C#]

namespace TimeOutBtn

{

    public class TimeOutButton : Button

    {

       

    }

}

Bir sonraki adımda hemen kontrolümüze yeni bir Property tanımlayalım. Property'miz sayesinde kullanıcıların düğmenin ne kadar süre aktif kalacağını tanımlayabilecekler.

[VB]

    Private PTimeOut As Integer

    Public Property TimeOut() As Integer

        Get

            Return PTimeOut

        End Get

        Set(ByVal value As Integer)

            PTimeOut = value

        End Set

    End Property

[C#]

        public int TimeOut { get; set; }

Düğmemiz ilk olarak sayfada gözüktüğünde hemen işlemlere başlamamız gerekiyor. İlk olarak düğmenin için sayaç bilgisi yazacak yeni bir kontrol eklememiz şart. Düğmenin Content özelliği duruma göre doğrudan bir String olabilir veya Content içerisinde farklı Silverlight nesneleri bulunabilir. Tüm bunları göz önünde bulundurmak zorundayız.

[VB]

        Dim Container As New StackPanel

        Container.Orientation = Orientation.Vertical

        Container.HorizontalAlignment = Windows.HorizontalAlignment.Center

        Container.VerticalAlignment = Windows.VerticalAlignment.Center

 

        If Me.Content.GetType() Is System.Type.GetType("System.String") Then

            Dim TextBl As New TextBlock

            TextBl.Text = Me.Content

            Container.Children.Add(TextBl)

        Else

            Container.Children.Add(Me.Content)

        End If

        Container.Children.Add(MyBox)

        Me.Content = Container

[C#]

            StackPanel Container = new StackPanel();

            Container.Orientation = Orientation.Vertical;

            Container.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;

            Container.VerticalAlignment = System.Windows.VerticalAlignment.Center;

 

            if (object.ReferenceEquals(this.Content.GetType(), System.Type.GetType("System.String"))) {

                TextBlock TextBl = new TextBlock();

                TextBl.Text = this.Content.ToString();

                Container.Children.Add(TextBl);

            }

            else {

                Container.Children.Add(this.Content as UIElement);

            }

            Container.Children.Add(MyBox);

            this.Content = Container;

Kodumuz içerisinde ilk olarak bir StackPanel yaratıyoruz. StackPanel'in özelliklerini ayarladıktan sonra hemen düğmemize atanmış Content'i kontrol ediyoruz. Amacımız Content içerisinde her ne varsa hepsini StackPanel içine eklemek. Sonrasında bizim kalan saniye miktarını göstereceğimiz TextBlock'u da yine StackPanel içerisine ekleyerek StackPanel'i de düğmenin Content'i yapacağız. Böylece bu TimeOutButton kontrolünü kullananlar düğmenin Content'ine ne koyarlarsa koysunlar kalan saniye miktarı sürekli bu Content'in içerisinde gösterilecek.

Eğer düğmeye atanmış Content String tipindeyse bu String'i alıp yeni bir TextBlock yaratarak içerisine yerleştiriyoruz. TextBlock'umuzu da StackPanel içine koyuyoruz. Eğer Content String değilse demek ki kullanıcı düğmenin Content'ine bir Silverlight nesnesi koymuş. Bu durumda söz konusu nesneyi alıp doğrudan StackPanel içine koyabiliriz. Son olarak kodumuzda gözükmeyen fakat uygulamamızda global bir değişken olarak yarattığımız MyBox adındaki TextBlock'u da StackPanel'e ekliyoruz ve StackPanel'i de düğmenin Content'i yapıyoruz. MyBox kontrolünü global yaratmamızın nedeni ileriki adımlarda MyBox'ın içeriğine sürekli kalan saniye miktarını yazdıracak olmamız.

[VB]

    Dim MyBox As New TextBlock

    WithEvents Timer As New System.Windows.Threading.DispatcherTimer

[C#]

        TextBlock MyBox = new TextBlock();

        System.Windows.Threading.DispatcherTimer Timer = new System.Windows.Threading.DispatcherTimer();

Global değişkenimiz arasında bir de DispatcherTimer bulunuyor. Bu Timer ile kalan saniye miktarını sürekli hesaplayıp kontrol ederek düğmenin içine yazdıracağız.

[VB]

    Private Sub Timer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer.Tick

        If PTimeOut <= 0 Then

            Timer.Stop()

            MyBox.Visibility = Windows.Visibility.Collapsed

            Me.IsEnabled = False

        Else

            PTimeOut -= 1000

            MyBox.Text = (PTimeOut / 1000).ToString  + " saniye kaldı."

        End If

    End Sub

[C#]

        private void Timer_Tick(object sender, System.EventArgs e)

        {

            if (TimeOut <= 0)

            {

                Timer.Stop();

                MyBox.Visibility = System.Windows.Visibility.Collapsed;

                this.IsEnabled = false;

            }

            else {

                TimeOut -= 1000;

                MyBox.Text = (TimeOut / 1000).ToString() + " saniye kaldı.";

            }

        }

Kodumuzda kalan süreyi PTimeOut adındaki private değişkenimizde saklayacağız. Eğer kalan süre sıfırın altında ise hemen Timer'ımızı durduruyor ve kalan süreyi gösteren TextBlock'umuz olan MyBox'ı sahneden kaldırıp düğmeyi de pasif hale getiriyoruz. Kalan süre sıfırdan büyük olduğu sürece MyBox TextBlock içerisine gerekli uyarıyı yazdırıp kalan süreyi Timer'ın Intervali kadar azaltıyoruz.

Expression Blend içerisinde hazırladığımız yeni kontrol.
Expression Blend içerisinde hazırladığımız yeni kontrol

Artık kontrolümüz hazır. Projemizi Blend ile açtığımızda Asset Library içerisinde Custom Controls tabında kontrolümüzü görebiliyoruz. Sahneye bir TimeOutButton ekleyip TimeOut özelliğini de ayarladıktan sonra kontrolümüzü kullanabiliriz.

<UserControl x:Class="SilverlightApplication47.Page"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   Width="400" Height="300" xmlns:TimeOutBtn="clr-namespace:TimeOutBtn;assembly=TimeOutBtn">

    <Grid x:Name="LayoutRoot" Background="White">

          <TimeOutBtn:TimeOutButton TimeOut="5000" Height="72" HorizontalAlignment="Left" Margin="56,48,0,0" VerticalAlignment="Top" Width="128" Content="TimeOutButton"/>

    </Grid>

</UserControl>

Hepinize kolay gelsin. Uygulamanın tam kodunu aşağıda inceleyebilirsiniz.

[VB]

Public Class TimeOutButton

    Inherits Button

 

    Private PTimeOut As Integer

    Public Property TimeOut() As Integer

        Get

            Return PTimeOut

        End Get

        Set(ByVal value As Integer)

            PTimeOut = value

        End Set

    End Property

 

    Dim MyBox As New TextBlock

    WithEvents Timer As New System.Windows.Threading.DispatcherTimer

 

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

        Dim Container As New StackPanel

        Container.Orientation = Orientation.Vertical

        Container.HorizontalAlignment = Windows.HorizontalAlignment.Center

        Container.VerticalAlignment = Windows.VerticalAlignment.Center

 

        If Me.Content.GetType() Is System.Type.GetType("System.String") Then

            Dim TextBl As New TextBlock

            TextBl.Text = Me.Content

            Container.Children.Add(TextBl)

        Else

            Container.Children.Add(Me.Content)

        End If

        Container.Children.Add(MyBox)

        Me.Content = Container

        Timer.Interval = New TimeSpan(0, 0, 1)

        Timer.Start()

    End Sub

 

    Private Sub Timer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer.Tick

        If PTimeOut <= 0 Then

            Timer.Stop()

            MyBox.Visibility = Windows.Visibility.Collapsed

            Me.IsEnabled = False

        Else

            PTimeOut -= 1000

            MyBox.Text = (PTimeOut / 1000).ToString  + " saniye kaldı."

        End If

    End Sub

End Class

[C#]

using System;

using System.Net;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Documents;

using System.Windows.Ink;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Animation;

using System.Windows.Shapes;

 

namespace TimeOutBtn

{

    public class TimeOutButton : Button

    {

        public int TimeOut { get; set; }

 

        TextBlock MyBox = new TextBlock();

        System.Windows.Threading.DispatcherTimer Timer = new System.Windows.Threading.DispatcherTimer();

 

        public TimeOutButton()

        {

            this.Loaded += new RoutedEventHandler(TimeOutButton_Loaded);

            Timer.Tick += new EventHandler(Timer_Tick);

        }

 

        private void TimeOutButton_Loaded(object sender, System.Windows.RoutedEventArgs e)

        {

            StackPanel Container = new StackPanel();

            Container.Orientation = Orientation.Vertical;

            Container.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;

            Container.VerticalAlignment = System.Windows.VerticalAlignment.Center;

 

            if (object.ReferenceEquals(this.Content.GetType(), System.Type.GetType("System.String"))) {

                TextBlock TextBl = new TextBlock();

                TextBl.Text = this.Content.ToString();

                Container.Children.Add(TextBl);

            }

            else {

                Container.Children.Add(this.Content as UIElement);

            }

            Container.Children.Add(MyBox);

            this.Content = Container;

            Timer.Interval = new TimeSpan(0, 0, 1);

            Timer.Start();

        }

        private void Timer_Tick(object sender, System.EventArgs e)

        {

            if (TimeOut <= 0)

            {

                Timer.Stop();

                MyBox.Visibility = System.Windows.Visibility.Collapsed;

                this.IsEnabled = false;

            }

            else {

                TimeOut -= 1000;

                MyBox.Text = (TimeOut / 1000).ToString() + " saniye kaldı.";

            }

        }

    }

}

Daron Yöndem
MVP, MCT, MCPD, MCITP, MCTS
MCSD, MCAD, MCDBA, MCP, ACP, ICSD
Blog: http://daron.yondem.com
Sorularınız için: http://daron.yondem.com/tr/sorusor