Silverlight Toolkit'ten AutoCompleteBox kullanımı.

0 dakikada yazıldı

6746 defa okundu

Düzenle

Bu yazımızda Silverlight Toolkit
ile beraber gelen AutoCompleteBox kontrolünü inceleyeceğiz.
Bilgisayarınızda Silverlight Toolkit yükledikten sonra Toolkit
içerisindeki tüm kontrolleri Visual Studio içerisinde Toolbox'ta
görebilirsiniz. Ayrıca Toolkit DLL'lerini referans alarak kontrolleri
elle XAML sayfalarınıza ekleme şansınız da var. Örneğin AutoCompleteBox
kontrolünü inceleyecek olursak; bir sayfaya söz konusu kontrolü eklemek
için ilk olarak Toolkit Assembly'lerinden
System.Windows.Controls.Input Assembly'sini projenize referans
almanız sonrasında da System.Windows.Controls NameSpace'i altından
kontrolü bulmanız gerekecektir.

[XAML]

<UserControl
xmlns
:input="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input"
x:Class="SilverlightApplication54.MainPage"

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

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

   Width="400"
Height
="300">

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

        <input:AutoCompleteBox></input:AutoCompleteBox>

    </Grid>

</UserControl>

Yukarıda gördüğünüz basit örnek içerisinde XAML root elementimizde
gerekli input XML namespace'i tanımlanmış durumda. Böylece artık input
namespace'i üzerinden AutoCompleteBox kontrolümüzü kullanabiliriz.
Daha önce de bahsettiğim üzere eğer Visual Studio'nun Toolbox'ından söz
konusu kontrolü kod tarafına sürükle bırak tekniği ile yerleştirirseniz
zaten tüm bu işlemleri otomatik olarak gerçekleştirilebiliyor.

Haydi veriye bağlayalım!

Kontrolümüzü artık sahneye yerleştirdiğimize göre hemen çalıştırmak ve
sonucu görmek isteyeceğiz fakat onun öncesinde tabi ki bir veri
bağlantısı yapmamız şart. Kullanıcılar kutuya birşey yazarken
AutoComplete kısmında neler gösterilecek?

[XAML]

<UserControl
xmlns
:input="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input"
x:Class="SilverlightApplication54.MainPage"

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

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

   Width="400"
Height
="300">

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

        <input:AutoCompleteBox
x
:Name="myAutoCompleteBox" VerticalAlignment="Top"></input:AutoCompleteBox>

    </Grid>

</UserControl>

[VB]

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

        Dim Secenekler() As String
= {"Silverlight", "Silvernight", "Silverfight", "SilverMonth"}

        myAutoCompleteBox.ItemsSource = Secenekler

    End Sub

[C#]

        void MainPage_Loaded(object sender, RoutedEventArgs e)

        {

            string[] Secenekler = {
"Silverlight", "Silvernight", "Silverfight", "SilverMonth" };

            myAutoCompleteBox.ItemsSource = Secenekler;

        }

Yukarıdaki kod içerisinde aslında basit bir şekilde tüm seçenekleri
doğrudan AutoCompletebox'ın ItemsSource'una atamış oluyoruz.
Sonrasında AutoCompleteBox kendi içerisinde gerekli filtrelemeleri
kullanıcılar metin giriş yaptıkça gerçekleştirerek sonucu gösteriyor.

Silverlight içerisinde basit bir AutoCompleteBox
Silverlight içerisinde basit bir AutoCompleteBox

Peki ya web servisinden alacak olsak sonuçları?

Bir önceki örneği incelerken büyük ihtimal ile kendi içinizden "Eee
peki kocaman bir listemiz varsa hepsini istemciye mi alacağız?
" diye
sormuşsunuzdur. Tabi ki hayır. Aslında normal şartlarda yapmamız gereken
şey AutoCompleteBox içerisine yazılan kelimeyi sunucuya göndermek ve
geri gelen sonucu da AutoCompleteBox'ın AutoComplete bölümünde
göstermek. İşte bu işlemi yapabilmek için AutoCompletebox'ın
Populating eventını kullanıyoruz.

Örneğimizde Tavsiye adında bir webmethod kullanacağız. Web
servisinin yazımı kısmına girmeyeceğim fakat kabaca bahsetmek gerekirse
istemciden aranacak kelimeyi alan ve veritabanına gidip uygun
AutoComplete seçeneklerini bir list olarak döndüren bir webmethod
yeterli olacaktır.

[VB]

    Private Sub myAutoCompleteBox_Populating(ByVal sender As Object,
ByVal e As
System.Windows.Controls.PopulatingEventArgs) Handles myAutoCompleteBox.Populating

        e.Cancel = True

        Dim servis As New
ServiceReference1.Service1Client

        AddHandler
servis.TavsiyelerCompleted, AddressOf
Servis_TavsiyelerCompleted

        servis.TavsiyelerAsync(myAutoCompleteBox.Text)

    End Sub

[C#]

        public MainPage()

        {

            InitializeComponent();

            this.Loaded += new RoutedEventHandler(MainPage_Loaded);

            myAutoCompleteBox.Populating += new PopulatingEventHandler(myAutoCompleteBox_Populating);

        }

 

        void
myAutoCompleteBox_Populating(object
sender, PopulatingEventArgs e)

        {

            e.Cancel = true;

            ServiceReference1.Service1Client servis = new ServiceReference1.Service1Client();

            servis.TavsiyelerCompleted += Servis_TavsiyelerCompleted;

            servis.TavsiyelerAsync(myAutoCompleteBox.Text);

        }

Yukarıdaki kodumuzda AutoCompleteBox'ın Populating durumunu
yakalayarak hemen e.Cancel değerini True yaparak Populate
işlemini iptal ediyoruz. Neden mi? Çünkü Populate işlemi, yani
AutoComplete listesinin gösterilmesi işlemi şu anda yapılamaz. İşlemi
yapabilmek için bizim Webmethod'umuza parametreyi vermemiz, söz konusu
bilginin sunucuya gitmesi ve en önemli cevabın gelmesi gerekiyor! Cevap
gelmeden Populate edemeyiz! O nedenle burada hemen Populate
işlemini iptal ediyoruz. Sonrasında WebServis'imizden bir kopya alıp
Completed durumu da ayrı bir handler'a bağlayıp elimizdeki
AutoCompleteBox içerisinde metni Tavsiyeler adındaki Webmethod'umuza
gönderiyoruz.

[VB]

    Private Sub Servis_TavsiyelerCompleted(ByVal sender As Object,
ByVal e As
ServiceReference1.TavsiyelerCompletedEventArgs)

        myAutoCompleteBox.ItemsSource = e.Result

        myAutoCompleteBox.PopulateComplete()

    End Sub

[C#]

        private void Servis_TavsiyelerCompleted(object sender,
ServiceReference1.TavsiyelerCompletedEventArgs e)

        {

            myAutoCompleteBox.ItemsSource = e.Result;

            myAutoCompleteBox.PopulateComplete();

        }

Populating durumunda çağırdığımız web servisimizin Completed durumunda
artık veri elimizde olduğunda göre doğrudan AutoCompleteBox'ımızın
ItemsSource'una verebiliriz. Son olarak tabi ki Populate işlemini
bitirdiğimizi de AutoCompleteBox'a belirtmemiz gerek ki hemen sonucu
kullanıcıya göstersin.

Arama şeklini nasıl değiştiririz?

Varsayılan ayarları ile AutoCompleteBox'lar kendilerine verilen verinin
içinde arama yaparken kullanıcının yazdığı metinile başlayan sonuçları
gösterirler. Bunun değiştirmenin yolu AutoCompletebox'ların SearchMode
özelliğinde yatıyor.

Veri kaynağında nasıl arama yapılacağını belirleyin.
Veri kaynağında nasıl arama yapılacağını belirleyin.

Peki bu arama sistemleri size yetmedi ve daha da özelleştirmek
isterseniz ne yapabilirsiniz? Filtreleme işlemini tamamen ele alma
şansınız da var. Bu durum özellikle AutoCompleteBox'a kendi nesne
tiplerinizi bağladığınızda çok anlamlı olabilir. Filtreleme esnasından
belki de sadece ItemsSource'a verdiğiniz nesnelerin belirli
Property'lerine göre ayrı ayrı mantıklarıda aramalar yapılsın
isteyebilirsiniz.

[VB]

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

        myAutoCompleteBox.ItemFilter = AddressOf Arama

    End Sub

 

    Function Arama(ByVal metin As String,
ByVal nesne As ServiceReference1.Service1Urun) As Boolean

        If nesne.Adi.Contains(metin)
Then

            Return True

        Else

            Return False

        End If

    End Function

[C#]

        public MainPage()

        {

            InitializeComponent();

            myAutoCompleteBox.ItemFilter = Arama;

        }

 

        bool Arama(string metin, ServiceReference1.Service1Urun
nesne)

        {

            if
(nesne.Adi.Contains(metin)) {

                return true;

            }

            else {

                return false;

            }

        }

Yukarıdaki örneğimizde AutoCompleteBox'ın ItemFilter'ına yeni bir
metod atıyoruz. Bu metod parametre olarak o anda filtrelenmek
istenen Item'ı, yani benim örneğimde ServiceReference ile
beraber gelen tipte bir nesneyi ve filtrelemede kullanılacak metni
alıyor. Sonrasında gerekli kontrolleri yaptıktan sonra geriye
filtrelediğiniz her bir nesnenin gösterilip gösterilmeyeceğine dair
birer Boolean değer döndürmeniz yeterli olacaktır.

Görsel özelleştirmeler...

Makalemizde incelediğimiz tüm özellikleri kullandınız, kendi
nesnelerinizi web servisi ile döndürdünüz ve özel bir filtrelemede de
eklediniz. Fakat AutoComplete listesinde daha çok detay göstermek
istiyorsunuz. Bu durumda gelin AutoCompleteBox'ın ItemTemplate'ini bir
inceleyelim.

[XAML]

        <input:AutoCompleteBox
x
:Name="myAutoCompleteBox" VerticalAlignment="Top">

            <input:AutoCompleteBox.ItemTemplate>

                **** <DataTemplate>

                    <Grid
HorizontalAlignment="Stretch"
Width
="Auto">

                        <Grid.ColumnDefinitions>

                            <ColumnDefinition Width="250"
/>

                            <ColumnDefinition Width="250"
/>

                        </Grid.ColumnDefinitions>

                        <TextBlock
Foreground
="Red" Grid.Column="0"
Text
="{Binding
Adi
}" />

                        <TextBlock
Foreground
="Red" Grid.Column="1"
Text
="{Binding
Soyadi
}" />

                    </Grid>

                </DataTemplate>

            </input:AutoCompleteBox.ItemTemplate>

        </input:AutoCompleteBox>

Kod içerisinde de gördüğünüz üzere AutoCompleteBox'ın ItemTemplate'i
aslında kendi içerisinde AutoComplete kısmında tekrar ettiği
satırları tanımlıyor. Bu satırların tasarımı aslında arkaplanda bir
ListBox'ın Item'larıdır. Bizim örneğimizde ulaşmaya çalıştığımız
işlevsellik iki veya daha çok Property'i kullanıcıya gösterirken arka
plandaki filtrelememiz ile de bir AutoComplete işlevselliği sağlamak.
Zaten hali hazırda AutoCompleteBox'ımıza nesnelerimizi ItemsSource
üzerinden aktardığımız için o nesnelerin tüm Property'lerine dair
Binding'leri de ItemTemplate içerisinde ayarlayabiliyoruz.

AutoComplete kısmı özelleştirilmiş bir AutoCompleteBox.
AutoComplete kısmı özelleştirilmiş bir AutoCompleteBox.

Taktikler

Eğer herhangi bir AutoCompleteBox'ın ItemsSource'una kendi
tanımladığınız tiplerden oluşan listeler verirseniz AutoComplete
bölümünde saçma metinler görebilirsiniz. Normal şartlarda bir String
Array vs verildiğinde herhangi bir sorun olmuyor fakat kendi
tanımladığınız sınıflarda veya web servislerinden Proxy aracılığı ile
aldığınız sınıflarda sorun yaşayabilirsiniz. Bu durumu düzeltmenin yolu
kendi sınıflarınız için birer ToString extension'ı yazmak olabilir.
AutoCompleteBox kendisine verilen tüm nesnelerin üzerinden ToString
metodunu çağırarak gelen metni AutoComplete kısmında gösterir. O nedenle
siz de kendi sınıflarınızda ToString'i override ederek kendi istediğiniz
verileri geri döndürebilirsiniz.

[VB]

Namespace ServiceReference1

    Partial Public Class Service1Urun

        Public Overrides Function ToString() As String

            Return Me.Adi & Me.Soyadi

        End Function

    End Class

End Namespace

[C#]

namespace ServiceReference1

{

    public partial class Service1Urun

    {

        public override string ToString()

        {

            return this.Adi + this.Soyadi;

        }

    }

}

Yukarıdaki örnek kod içerisinde ServiceReference1 adında bir servis
referansı ile beraber gelen Service1Urun adındaki nesnenin ToString
metodunu override ediyoruz. Artık söz konusu nesneden sonra ToString
denildiğinde buradaki Function çalışacak ve nesnenin Adi ile
Soyadi Property'lerini birleştirerek geri döndürecek. Böylece
AutoCompleteBox da bu ToString'den gelen veriyi gösterebilecek.

Otomatik seçilseler...

AutoComplete listesini gösteriyorsunuz fakat her seferinde kullanıcının
bir kayıt seçmek zorunda kalmasını da istemiyorsunuz. Belki de en uygun
seçecek hemen seçilebilir şekilde gelse? Nasıl mı?

IsTextCompletionEnabled = True olursa...
IsTextCompletionEnabled = True olursa...

AutoCompleteBox'ın IsTextCompletionEnabled özelliği True yaparsanız
yukarıdaki gibi kullanıcılar metin girişi yaparken bir yandan da en
uygun seçeneği seçtirebilirsiniz. Böylece anında seçimi onaylayarak
kullanıcılar hızlıca işleme devam edebilirler.

Hepinize kolay gelsin.