İlkay İlknur

just a developer...

Windows 8 Metro Style Uygulamalarda GridView Kontrolünde Gruplama - C# & XAML

Merhaba Arkadaşlar,

Geçen yazımızda sizlerle Windows 8 Metro Style GridView kontrolünü incelemiştik ve yazımızın sonunda da GridView'ın aslında içerisindeki itemları gruplayarak gösterme gibi bir özelliği olduğundan kısaca bahsederek topu bu makaleye atmıştık. :)

Bir GridView kontrolü içerisindeki elemanları gruplu olarak göstermemiz için yapmamız gereken bazı değişiklikler bulunmakta.

Gruplanmış Data İle Çalışmak

Bu değişikliklerden ilki elimizdeki data ile ilgili. Önceki yazımızda yemek listesi Windows 8 tarafına tek bir liste olarak gelmekteydi. Ancak şimdi gruplama yapacağımız için artık yemek listesinin yemeğin kategorisine göre gruplanmış olarak gelmesi gerekmekte. Bu nedenle servise yaptığımız metot çağırısında bize dönecek olan tip içerisinde bir takım revizyonlara gideceğiz ve aşağıdaki gibi bir dönüş formatı kullanacağız.

[sourcecode lang="csharp"] [DataContract] public class FoodCategory { [DataMember] public string CategoryName { get; set; } [DataMember] public List<Food> Foods { get; set; } } [/sourcecode]

Yemekler için bu şekilde bir dış kategori sınıfı koyduktan sonra gördüğünüz gibi kategori tipi içerisinde de o kategoriye ait olan yemeklerin listesi gelecek.

[sourcecode lang="csharp"] [DataContract] public class Food { [DataMember] public string FoodName { get; set; } [DataMember] public decimal Price { get; set; } [DataMember] public string ImageUrl { get; set; } } [/sourcecode]

Web servis tarafında bu şekilde bir revizyona gittikten sonra artık GetFoods metodunun dönüş tipi de List<Food> yerine List<FoodCategory> olacak.

Evet artık elimizde gruplanmış veriler var ve web servis metodundan verileri çekip GridView kontrolüne bağlayabilir durumdayız.

Not : Her zaman datanın geleceği servislerde gruplama yapma imkanına sahip olamayabiliriz.(Örneğin RSS, veya 3.rd party servisler). Bu gibi durumlarda eğer yine gruplanmış GridView kontrolü ile çalışma gibi bir ihtiyaç olursa Windows 8 tarafında da bu gruplama işlemi yapılabilir. Tabi gelen datanın formatına göre :) Ayrıca biraz performans kaybını göze almak gerekebilir. ;)

GridView Kontrolünde Gruplama

Elimizde gruplanmış datalarımız var ve  GridView kontrolümüz de sahnede hazır. Peki hemen ItemsSource propertysine elimizdeki koleksiyonu versek bizim için gruplanmış olarak gösterir mi ? :)

Bu işlem o kadar da kolay değil. :)  Öncelikle GridView içerisindeki bazı templateları yaratmamız gerekmekte ve elimizdeki datayı da farklı bir tip üzerinden GridView kontrolüne göndermeliyiz. Neyse çok fazla işlemi karıştırmadan adım adım ilerleyelim.

Geçen yazımızda olduğu gibi sahne üzerinde bir GridView kontrolümüz bulunmakta.

[sourcecode lang="xml"] <GridView x:Name="foodGrid" Margin="50,140,15,15"/> [/sourcecode]

İlk olarak GridView kontrolüne elimizdeki gruplanmış dataları nasıl göstermesi gerektiğini bildirmemiz gerekmekte. Bunun için kontrole Visual Studio 2012'den veya Blend üzerinden sağ tıkladığımızda karşımıza şu şekilde bir seçenek çıkmakta.

Bu seçeneğe tıkladıktan sonra artık GridView kontrolünün gruplayarak gösterme templatelarını aktif hale getirmekteyiz ve aşağıda da göreceğiniz gibi "Edit GroupStyle" seçeneği artık aktif hale gelmekte ve bazı templatelar karşımıza çıkmakta.

Aslında tüm yapacağımız buradaki bazı templateları yaratarak GridView kontrolüne elimizdeki itemları nasıl göstermesi gerektiğini bildirmek. Şimdi ilk olarak kategori başlıklarının nasıl görüneceğini belirleyeceğimiz HeaderTemplate ile başlayalım.

[sourcecode lang="xml"] <GroupStyle.HeaderTemplate> <DataTemplate> <TextBlock FontSize="18.667" Text="{Binding CategoryName}"/> </DataTemplate> </GroupStyle.HeaderTemplate> [/sourcecode]

Kategori başlıklarını hallettikten sonra şimdi sıra geldi ilgili kategori içerisindeki elemanların nasıl bir düzende görüneceğine. Bunun için de GroupStyle içerisindeki ItemsPanel template'ını yaratmamız gerekmekte.

[sourcecode lang="xml"] <GroupStyle.Panel> <ItemsPanelTemplate> <VariableSizedWrapGrid Orientation="Horizontal" MaximumRowsOrColumns="3"/> </ItemsPanelTemplate> </GroupStyle.Panel> [/sourcecode]

Yukarıdaki tanımlama ile elimizdeki itemları bir VariableSizedWrapGrid içerisine alıyoruz. (VariableSizedGridView kontrolü aslında bildiğimiz WrapPanel kontrolünün biraz daha gelişmiş hali.Arasındaki farkları başka bir yazımızda inceliyor oluruz. :) ) VariableSizedWrapPanel içerisinde de itemları yatay olarak dizileceğini  ve bir satırda ve sütunda da maksimum 3 eleman olabileceğini MaximumRowsOrColumns propertysi ile belirtiyoruz.

Şimdi sıra geldi elimizde kategorileri nasıl bir layout ile göstereceğimize. Bunu da GridView kontrolü içerisindeki ItemsPanel template'ı ile gerçekleştiriyoruz.

[sourcecode lang="xml"] <ItemsPanelTemplate x:Key="ItemsPanelTemplate"> <StackPanel Orientation="Horizontal" /> </ItemsPanelTemplate> [/sourcecode]

Son olarak ise elimizdeki yemekleri nasıl göstereceğimize. Bunu da önceki yazımızdan da hatırlayacağınız üzere ItemTemplate ile gerçekleştiriyoruz.

[sourcecode lang="xml"] <DataTemplate x:Key="FoodTemplate"> <Grid> <Image HorizontalAlignment="Left" Height="246" VerticalAlignment="Top" Width="250" Stretch="UniformToFill" Source="{Binding ImageUrl}"/> <Border BorderThickness="1" HorizontalAlignment="Left" Height="22.393" Margin="0,223.607,0,0" VerticalAlignment="Top" Width="250" Background="Black" Opacity="0.4"> <TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Margin="3,2,0,0" Text="{Binding FoodName}"/> </Border> </Grid> </DataTemplate> [/sourcecode]

GridView tarafındaki templating maceralarımızın sonuna geldik ve son olarak elimizdeki datayı GridView kontrolüne bağlama işimiz kaldı. Yazımızın başında klasik ItemsSource propertysine doğrudan elimizdeki datayı veremeyeceğimizden bahsetmiştik. Şimdi bu kısma biraz değinelim.

CollectionViewSource ile Gruplanmış Data Gösterimi

Silverlight tarafıyla daha önce uğraşanlar için CollectionViewSource tipi aslında çokta yabancı olan bir tip değil. Silverlight tarafındayken de elimizdeki verileri gruplu olarak göstermek istediğimizde CollectionViewSource kullanıp bu işlemi hızlı bir şekilde yapabiliyorduk. İşte Windows 8 Metro Style tarafında da yine CollectionViewSource tipini kullanarak bu gruplama işlemini hızlıca yapabiliyoruz. Peki burada CollectionViewSource nasıl bir işlev görüyor derseniz aslında elinizdeki gruplanmış datalar ile GridView arasında bir proxy görevi görüyor ve bizim belirlediğimiz formatta dataları alıp GridView kontrolüne gönderiyor.

CollectionViewSource tipi ile çalışmak da aslında oldukça basit. İlk olarak XAML tarafında resourcelar içerisinde bir CollectionViewSource tipinden instance tanımlıyoruz ve daha sonra GridView'ın ItemsSource propertysinin de bu tipten beslenmesi için binding işlemi yapıyoruz.

[sourcecode lang="xml"] <Page.Resources> <CollectionViewSource x:Name="foodDataSource" ItemsPath="Foods" IsSourceGrouped="True"/> </Page.Resources> [/sourcecode]

Burada IsSourceGrouped propertysine True değer vererek verdiğimiz datanın aslında gruplanmış olduğunu CollectionViewSource tipine bildiriyoruz. Ayrıca ItemsPath propertysine de Foods değerini vererek CollectionViewSource'un kategori içerisindeki yemeklerin hangi property içerisinde bulacağını da bildirmiş oluyoruz.

GridView kontorolü üzerinde yaptığımız binding işlemi ise şu şekilde.

[sourcecode lang="xml"] <GridView x:Name="foodGrid" ItemsSource="{Binding Source={StaticResource foodDataSource}}" Margin="50,140,15,15" ItemTemplate="{StaticResource FoodTemplate}" ItemsPanel="{StaticResource ItemsPanelTemplate}"/> [/sourcecode] Kod tarafına geçtiğimizde ise artık elimizdeki listeyi GridView kontrolüne vermek yerine sayfa içerisinde tanımladığımız CollectionViewSource tipinin Source'una elimizdeki listeyi veriyoruz. [sourcecode lang="csharp"] protected async override void OnNavigatedTo(NavigationEventArgs e) { FoodService.ServiceClient client = new FoodService.ServiceClient(); ObservableCollection<FoodCategory> foodList = await client.GetFoodsAsync(); foodDataSource.Source = foodList; } [/sourcecode] Uygulamamızın sonunda yaptığımız templatingler de dahil olmak üzere oluşan XAML şu şekilde. [sourcecode lang="xml"] <Page x:Class="App4.MainPage" IsTabStop="false" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:App4" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Page.Resources> <CollectionViewSource x:Name="foodDataSource" ItemsPath="Foods" IsSourceGrouped="True"/> <DataTemplate x:Key="FoodTemplate"> <Grid> <Image HorizontalAlignment="Left" Height="246" VerticalAlignment="Top" Width="250" Stretch="UniformToFill" Source="{Binding ImageUrl}"/> <Border BorderThickness="1" HorizontalAlignment="Left" Height="22.393" Margin="0,223.607,0,0" VerticalAlignment="Top" Width="250" Background="Black" Opacity="0.4"> <TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Margin="3,2,0,0" Text="{Binding FoodName}"/> </Border> </Grid> </DataTemplate> <ItemsPanelTemplate x:Key="ItemsPanelTemplate"> <StackPanel Orientation="Horizontal" /> </ItemsPanelTemplate> </Page.Resources> <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> <GridView x:Name="foodGrid" ItemsSource="{Binding Source={StaticResource foodDataSource}}" Margin="50,140,15,15" ItemTemplate="{StaticResource FoodTemplate}" ItemsPanel="{StaticResource ItemsPanelTemplate}"> <GridView.GroupStyle> <GroupStyle> <GroupStyle.HeaderTemplate> <DataTemplate> <TextBlock FontSize="18.667" Text="{Binding CategoryName}"/> </DataTemplate> </GroupStyle.HeaderTemplate> <GroupStyle.Panel> <ItemsPanelTemplate> <VariableSizedWrapGrid Orientation="Horizontal" MaximumRowsOrColumns="3"/> </ItemsPanelTemplate> </GroupStyle.Panel> </GroupStyle> </GridView.GroupStyle> </GridView> </Grid> </Page> [/sourcecode]

Şimdi uygulamamızı çalıştıralım ve çalışmamızın sonucunda nasıl bir görünüm elde etmişiz görelim :)

Gördüğünüz gibi artık verilerimiz gruplanmış bir şekilde GridView kontrolünde görüntülenebilmekte ve mantıksal gruplar halinde kullanıcıya sunularak kısa bir development eforuyla kullanıcı deneyimi arttırılabilmekteyiz. İlk başlarda template sayısı fazla olduğundan dolayı karmaşıklık olabilir ancak tam olarak templateları anladıktan sonra hemen hızlı bir şekilde gruplamayı uygulamalarınıza entegre edebilirsiniz. ;)

Bir sonraki yazımızda görüşmek üzere.



Yorum Gönder