Silverlight 2.0 içerisinde ScrollViewer kullanımı.

0 dakikada yazıldı

6709 defa okundu

Düzenle

Herhangi bir içeriği Silverlight 2.0 arayüzlerinde göstermek
istediğinizde özellikle veri bağlanabilir çoğu kontrolün kendi
içerisinde "ScrollBar" (Kaydırma Çubukları) içerdiğini görebilirsiniz.
Fakat bazı durumlarda bu hazır kontrolleri kullanmadığınızda veya
scrollbar özelliği bulunmayan bazı yapı taşı niteliğinde kontrolleri
beraber kullanmak istediğiniz ayrıca bir ScrollBar'a ihtiyacınız
olabilir. Bu gibi durumlarda bize scrollbar özellikleri ekleme konusunda
ScrollViewer kontrolü yardımcı oluyor.

Yapacağımız ilk örnekte 1024*768 piksel büyüklüğünde bir resmi
uygulamamıza ekleyeceğiz. Fakat biz bu resim nesnesini tam ekran
göstermek istemiyoruz. Uygulamamız içerisinde ufak bir karede göstererek
insanların istiyorlarsa ScrollBar'lar aracılığı ile resmi gezmesini
istiyoruz. Bu durumda aslında yapmamız gereken çok basit. Aşağıdaki XAML
kodunu yaratacak şekilde Image nesnemizi bir ScrollViewer
içerisine yerleştirmemiz yeterli.

<UserControl
x:Class="ScrollBar.Page"

    xmlns="http://schemas.microsoft.com/client/2007"

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

    Width="400" Height="300" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">

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

      <ScrollViewer Margin="0,0,0,0"

HorizontalScrollBarVisibility
="Auto" ****
VerticalScrollBarVisibility="Auto">

        <Image
Height="768" Width="1024"
Source="Forest.jpg"/>

      </ScrollViewer>

    </Grid>

</UserControl>

Gördüğünüz gibi ScrollViewer nesnemizin içerisinde kocaman bir resim
var. ScrollViewer içerisine programatik olarak farklı nesnelerin de
yerleştirilebiliyor olabilirdi. O nedenle biz ScrollViewer'a ait
HorizontalScrollBarVisibility ve VerticalScrollBarVisibility
özelliklerini de Auto yaparak ScrollBar'ların sadece gerektiğinde
gözükmesini sağladık. Zaten varsayılan ayarları ile maalesef yatay
ScrollBar gösterilmiyor o nedenle her halükarda bu ayarları değiştirmek
şart.

ScrollViewer kontrolü iş başında.
ScrollViewer kontrolü iş başında.

Kullanımın ne kadar basit olduğunu sanırım daha da anlatmaya gerek yok.
Gelin biraz daha karışık bir örneğe doğru yola çıkalım. Varsayalım ki
ScrollViewer ile beraber gelen kaydırma çubukları yerine kendi
oluşturduğunuz bazı düğmeleri kullanarak kaydırma işlemi yaptırmak
istiyorsunuz, bu durumda ne yapabilirdik?

İlk olarak örneğimizin görsel kısmını hazırlayarak uygulamamıza iki
düğme ekleyelim. Bu düğmeler rahatlıkla farklı görsellikler atanarak
daha anlamlı hale getirilebilir. Ben odak noktamızı kaybetmeme adına
düğmelerin görsel özellikleri ile ilgilenmeyeceğim.

<UserControl
x:Class="ScrollBar.Page"

    xmlns="http://schemas.microsoft.com/client/2007"

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

    Width="400" Height="300" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">

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

    <ScrollViewer Margin="0,0,63,0"

HorizontalScrollBarVisibility
="Hidden" ****
VerticalScrollBarVisibility="Hidden"
x:Name
="Scroll">

      <Image
Height="768" Width="1024"
Source="Forest.jpg"/>

    </ScrollViewer>

    <Button
Height="57" HorizontalAlignment="Right"
Margin="0,8,8,0"
VerticalAlignment="Top" Width="51" Content="Yukarı"
x:Name="Yukari"/>

    <Button
Height="46" HorizontalAlignment="Right"
Margin="0,0,8,8"
VerticalAlignment="Bottom"
Width="51" Content="Aşağı"
x:Name="Asagi"/>

  </Grid>

</UserControl>

Kodumuz içerisinde önemli birkaç nokta var. Bunlardan ilki ScrollViewer
kontrolümüzün VerticalScrollBarVisibility ve
HorizontalScrollBarVisibility özelliklerinin Hidden olarak
ayarlanmış olması gerektiği. Eğer bu özellikleri Disable olarak
ayarlarsanız maalesef birazdan yapacağımız şekilde ScrollViewer'ın
kaydırma özelliklerinden faydalanamayız. Oysa biz işimizi olabildiğince
basite indirgemek ve kolaylaştırmak istiyoruz. O nedenle bu özellikler
Hidden olması ve ScrollViewer'dan faydalanmamız şart. Bu haldeyken
zaten ScrollBar'lar hiçbir şekilde gözükmeyecektir.

Sahnemizde ayrıca iki adet de düğme var. Bu düğmelere her basıldığında
bir miktar scroll yaptırmak istiyoruz. Aslında bizim örneğimizde hem
yatay hem de dikey kaydırma çubukları gerektiği için toplam dört düğme
gerekirdi. Fakat ben şimdilik sadece dikey kaydırma çubuğunu simüle
edeceğim, aynı sistemi yatay için kullanmak size kalıyor.

Private Sub Asagi_Click(ByVal sender As Object,
ByVal e As System.Windows.RoutedEventArgs) Handles Asagi.Click

    If Scroll.ScrollableHeight > 0
Then

        Scroll.ScrollToVerticalOffset(Scroll.VerticalOffset + 10)

    End If

End Sub

 

Private Sub Yukari_Click(ByVal sender As Object,
ByVal e As System.Windows.RoutedEventArgs) Handles Yukari.Click

    If Scroll.ScrollableHeight > 0
Then

        Scroll.ScrollToVerticalOffset(Scroll.VerticalOffset - 10)

    End If

End Sub

Hem Yukari hem de Asagi adindaki düğmelerimize yukarıdaki
şekilde kodlarımızı yazdığımızda düğmelere her basıldığında ScrollViewer
içerisindeki resim 10 piksel yukarı veya aşağıya doğru kayıyor. Kodumuzu
incelediğimizde basit bir IF kontrolü ile ScrollViewer'ın yükseklik
olarak kaydırılabilip kaydırılamayacağını öğreniyoruz eğer
ScrollableHeight sıfırdan büyük ise demek ki kaydırma işlemi
yapabiliriz. Kaydırma işlemini yapabilmek için mevcut VerticalOffset
üzerinden konumu alarak üzerine 10 piksel ekleyip veya çıkartıp bu
konuma scroll edilebilmesi için de ScrollToVerticalOffset metodunu
kullanıyoruz. Bu metod almış olduğu Offset değerine scroll ediyor.

Daha kaygan bir Scroll olmaz mı?

Yukarıdaki örneğimizi denediğinizde düğmeye her bastığımızda 10
piksellik bir kayma göreceksiniz. Bu durum sizi de benim gibi rahatsız
ettiyse daha hoş bir çözüme doğru ilerleyebiliriz. Rahatsızlık yaratan
aslında iki konu var, birincisi kullanıcı kaydırma işlemine devam etmek
için milyonlarca kez düğmeye tıklamak zorunda. Bu hiç de hoş bir durum
değil. Oysa biz düğmeye tıklandığı anı yakalayıp kullanıcı düğmeyi
bırakana kadar kaydırmaya devam etsek süper olurdu. Düğmeye fare ile
tıklandığı ve bırakıldığı anları yakalamak için rahatlıkla
MouseLeftButtonDown ve MouseLeftButtonUp eventlarını
kullanabiliriz. Tek yapmamız gereken bu arada sürekli kaydırma işlemi
yapmak. Hatta bu kaydırma işlemini de 20 milisaniyede 1 piksel şeklinde
yaparsak aslında çok daha hoş bir kaydırma efekti yaratmış oluruz.

Peki tüm bunları nasıl yapacağız. Silverlight 2.0 Beta 1 ile beraber
gelen DispatchTimer nesnesini kullanacağız. Bu aslında bizim
bildiğimiz Winforms'daki Timer'dan pek farklı değil. Esasen tek farkı
istemci tarafında farklı bir Threat içerisinde çalışıyormuş gibi
davranması.

Dim Timer As Windows.Threading.DispatcherTimer

İlk olarak yukarıdaki şekilde Timer değişkenimizi global olarak
tanımladık. Global tanımlamamızın nedeni hem MouseLeftButtonDown hem
de MouseLeftButtonUp durumlarında bu Timer'a başvuracak olmamız.
Aslında yapacağımız esas işlemi Timer'ı MouseLeftButtonDown
durumunda yani kullanıcı düğmeye basında başlatmak ve
MouseLeftButtonUp durumunda ise yani kullanıcı düğmeyi bıraktığında
ise durdurmak.

    If Scroll.ScrollableHeight > 0
Then

        Timer = New
Windows.Threading.DispatcherTimer

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

        AddHandler Timer.Tick,
AddressOf TimerTick

        Timer.Start()

    End If

Yukarıdaki kodumuzu düğmemizin MouseLeftButtonDown durumuna
yazıyoruz. Kullanıcı düğmeye tıkladığı anda global değişkenimize yeni
bir DispatchTimer nesnesi aktararak Interval değerini 20
milisaniye olarak düzenliyoruz. Böyleceher 20 milisaniyede bir bir
sonraki adımda DispatchTimer nesnesine bağladığımız Tick
event-handları çalıştırılıyor olacak. Tüm ayarlarımızı tamamladıktan
sonra DispatchTimer'ın Start metodu ile işlemi başlatıyoruz.

Sub TimerTick(ByVal sender As Object,
ByVal e As EventArgs)

    Scroll.ScrollToVerticalOffset(Scroll.VerticalOffset + 1)

End Sub

Timer'ın her Tick durumunda daha önce kullandığımız kodu kullanarak
kaydırma işlemi yapıyoruz. Bu sefer Tick durumları 20 milisaniyede bir
olacağı için sadece 1 piksellik bir kayma yaratacağız.

Private Sub Asagi_MouseLeftButtonUp(ByVal sender As Object,
ByVal e As
System.Windows.Input.MouseButtonEventArgs) Handles Asagi.MouseLeftButtonUp

    Timer.Stop()

End Sub

Son olarak düğmenin MouseLeftButtonUp durumunda ise Timer'ımızı
durdurarak kayma işlemini sonlandırıyoruz. Uygulamamızı hem Asagi
hem de Yukari düğmeleri için tamamladığımızda kodumuz aşağıdaki
şekilde sonuçlanıyor.

Partial Public Class Page

    Inherits UserControl

 

    Public Sub New()

        InitializeComponent()

    End Sub

 

    Dim Timer As Windows.Threading.DispatcherTimer

 

    Private Sub Asagi_MouseLeftButtonDown(ByVal sender As Object,
ByVal e As
System.Windows.Input.MouseButtonEventArgs)
Handles
Asagi.MouseLeftButtonDown,
Yukari.MouseLeftButtonDown

        If Scroll.ScrollableHeight >
0 Then

            Timer = New
Windows.Threading.DispatcherTimer

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

            AddHandler Timer.Tick,
AddressOf TimerTick

            Timer.Start()

        End If

    End Sub

 

    Sub TimerTick(ByVal sender As Object,
ByVal e As EventArgs)

        If Yukari.IsFocused Then

            Scroll.ScrollToVerticalOffset(Scroll.VerticalOffset - 1)

        Else

            Scroll.ScrollToVerticalOffset(Scroll.VerticalOffset + 1)

        End If

    End Sub

 

    Private Sub Asagi_MouseLeftButtonUp(ByVal sender As Object,
ByVal e As
System.Windows.Input.MouseButtonEventArgs)
Handles
Asagi.MouseLeftButtonUp, Yukari.MouseLeftButtonUp

        Timer.Stop()

    End Sub

End Class

Yukarıdaki kod içerisinde MouseLeftButtonDown ve MouseLeftButtonUp
event-handlerlarının sadece birer kere bulunduğu dikkatinizi çekecektir.
Söz konusu event-handlerları her iki düğmeye de bağlamış durumdayız.
Aslında her iki düğmenin de sadece uygun zamanlarda Timer nesnesini
başlatması ve sonlandırma yeterli. Önemli olan Timer'ın Tick durumunda
içeriğini yukarı veya aşağıya kaydırılacağına karar verebiliyor olmak.
Bunun için de ben örneğimde Yukari düğmesinin IsFocused
özelliğinden faydalandım. Eğer bir düğmeye basılmış ise doğal olarak söz
konusu düğme Focus almış demektir. Böylece o an için hangi düğmeye
basılmakta olduğunu yakalayıp one göre işlem yapılabilir.

Hepinize kolay gelsin.