Xamarin.Forms ConfinstaApp Sample Bölüm 3
Selamlar,
Confinsta app in detaylarını incelemeye devam ediyoruz. Bu bölümde xamarin.forms un yeni gelen özellikleri ile de birlikte 1 gün gibi kısa bir sürede ne şekilde ui lar çıkartabileceğimizi örneklemeye çalıştığım Confinsta app de, kullanıcıların fotoğraflarının kimler tarafından beğenildiğini ve hangi fotoğraflarının beğenildiğini görecekleri ve kimlerin kendisini Follow ettiklerini görecekleri 2 tab lı sayfadan oluşan sayfamızı inceleyeceğiz.
Bu sayfa içerisinde kullandığım temel özellikler şöyle;
- Syncfusion TabView
- FlexLayout
- ListView, GroupedListView
- BindableSpan
gibi özellikler bulunuyor.
Sayfaların görüntülerini hatırlayalım.
Sayfanın en temel özelliği, parmak ile sağa sola swipe edilerek tabların geçişlerini de sağlayan Syncfusion ın TabView ı üzerine kurulu olması. syncfusion ın ChartBar ları dışında en çok kullandığım paketi bu paket. Bir çok uygulamada buna benzer swipe ile geçişi istenen tablı yapılar mevcut. Özellikle iOS native tarafta bile bunu yapmak için ayrı cocoaPod ihtiyaç duyacakken böyle bir yapıyı custom rendererlar ile yapmak çok akıl karı değil. Bu yüzden kullanmaya kaçınsam da, bazı durumlarda paralı paketleri kullanmak gerekebiliyor, özellikle zamanınız dar ise 🙂
Sayfa iki tab a ayrılmış durumda. Soldaki tab da kullanıcıların sizin resimlerinizden beğendiklerini listeliyoruz. Sağda ise sizi takip edilenler gösteriliyor. Özellikle sol taraftaki her bir kullanıcının altında “sizin şu resimleriniz beğendi” ile beraber resimlerin dinamil geldiğini görsem ve FlexLayout olmasa yine sinir olurdum. Ama bir önceki yazımda gördüğümüz gibi FlexLayout ile bu tarz ui lar çok basit hale geliyor.
Gelelim sayfanın xaml tarafına. Sayfada ki iki farklı ekranı da aslında aynı xaml dosyası içinde tanımlayabiliyoruz. Aslında tabii bunları ayrı ContentView lar olarak tanımlayıp TabView ın olduğu sayfada referanslarınıda verebilirdik (ilk yazıda Tabbed page template inde kullandığımız yapı gibi).
Sayfanın xaml tarafı şu şekilde.
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:tabView="clr-namespace:Syncfusion.XForms.TabView;assembly=Syncfusion.SfTabView.XForms" xmlns:controls="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin" x:Class="ConfinstaApp.Views.FeedActivityView"> <ContentPage.Content> <tabView:SfTabView VisibleHeaderCount="2" TabHeaderBackgroundColor="White" x:Name="mainTabView" Margin="0,20,0,0"> <tabView:SfTabItem Title="Following" TitleFontAttributes="Bold" TitleFontColor="Black" TitleFontSize="15"> <tabView:SfTabItem.Content> <StackLayout> <ListView x:Name="FollowingFeedListView" ItemsSource="{Binding FollowingItems}" SelectionMode="None" SeparatorVisibility="None" HasUnevenRows="true" RefreshCommand="{Binding LoadFollowingFeedListCommand}" IsPullToRefreshEnabled="true" IsRefreshing="{Binding IsBusy, Mode=OneWay}" CachingStrategy="RecycleElement"> <ListView.ItemTemplate> <DataTemplate> <ViewCell Appearing="ViewCell_Appearing"> <Grid RowSpacing="5" Padding="10"> <Grid.RowDefinitions> <RowDefinition Height="50"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="50"></ColumnDefinition> <ColumnDefinition Width="*"></ColumnDefinition> </Grid.ColumnDefinitions> <controls:CircleImage BorderThickness="2" BorderColor="#ab423f" WidthRequest="40" HeightRequest="40" Source="{Binding ProfileUrl}" Aspect="AspectFit" Grid.Row="0" Grid.Column="0"></controls:CircleImage> <Label LineBreakMode="TailTruncation" FontSize="Small" Grid.Column="1" Grid.Row="0" VerticalOptions="Center" TextColor="Black"> <Label.FormattedText> <FormattedString> <Span Text="{Binding Name}" FontAttributes="Bold" FontSize="Small"></Span> <Span Text=" liked some posts." TextColor="DarkGray" FontAttributes="None" FontSize="Small"></Span> </FormattedString> </Label.FormattedText> </Label> <FlexLayout x:Name="imagesLayout" Wrap="Wrap" JustifyContent="Start" Direction="Row" Grid.Row="1" Grid.Column="1"></FlexLayout> </Grid> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </StackLayout> </tabView:SfTabItem.Content> </tabView:SfTabItem> <tabView:SfTabItem Title="You" FontIconFontAttributes="Bold" TitleFontColor="Black" TitleFontSize="15"> <tabView:SfTabItem.Content> <StackLayout> <StackLayout> <ListView x:Name="AboutYouFeedListView" ItemsSource="{Binding GroupedItems}" SelectionMode="None" IsGroupingEnabled="True" GroupDisplayBinding="{Binding Key}" SeparatorVisibility="None" HasUnevenRows="true" RefreshCommand="{Binding LoadFollowingFeedListCommand}" IsPullToRefreshEnabled="true" IsRefreshing="{Binding IsBusy, Mode=OneWay}" CachingStrategy="RecycleElement"> <ListView.ItemTemplate> <DataTemplate> <ViewCell Appearing="ViewCell_Appearing"> <Grid RowSpacing="5" Padding="10"> <Grid.RowDefinitions> <RowDefinition Height="Auto"></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="40"></ColumnDefinition> <ColumnDefinition Width="*"></ColumnDefinition> <ColumnDefinition Width="100"></ColumnDefinition> </Grid.ColumnDefinitions> <controls:CircleImage BorderThickness="2" BorderColor="#ab423f" WidthRequest="30" HeightRequest="30" Source="{Binding ProfileUrl}" Aspect="AspectFill" Grid.Column= "0"></controls:CircleImage> <Label LineBreakMode="TailTruncation" FontSize="Small" Grid.Column="1" VerticalOptions="Center" MaxLines="3" TextColor="Black"> <Label.FormattedText> <FormattedString> <Span Text="{Binding Name}" FontAttributes="Bold" FontSize="Small"></Span> <Span Text=" lstarted following you" TextColor="DarkGray" FontAttributes="None" FontSize="Small"></Span> </FormattedString> </Label.FormattedText> </Label> <Button BackgroundColor="#3893e8" TextColor="White" Text="Follow" CornerRadius="10" WidthRequest="80" HeightRequest="40" Grid.Column="2"></Button> </Grid> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </StackLayout> </StackLayout> </tabView:SfTabItem.Content> </tabView:SfTabItem> </tabView:SfTabView> </ContentPage.Content> </ContentPage>
aslında ana yapı şu şekilde; Bir adet SFTabView. Bunun içerisine iki adet SfTabItem. Bunların içerisinde de yukarıda görmüş olduğunuz gibi sanki bir ContentPage in Content tag ının içini doldurur gibi sayfamızın xaml kodlarını dolduruyoruz.
<tabView:SfTabView VisibleHeaderCount="2" TabHeaderBackgroundColor="White" x:Name="mainTabView" Margin="0,20,0,0"> <tabView:SfTabItem Title="Following" TitleFontAttributes="Bold" TitleFontColor="Black" TitleFontSize="15"> <tabView:SfTabItem.Content> </tabView:SfTabItem.Content> </tabView:SfTabItem> <tabView:SfTabItem Title="You" FontIconFontAttributes="Bold" TitleFontColor="Black" TitleFontSize="15"> <tabView:SfTabItem.Content> <StackLayout> </tabView:SfTabItem.Content> </tabView:SfTabItem> </tabView:SfTabView>
Sayfanın backend tarafına bakığımızda durum aşağıdaki gibi. Sadece yine anasayfadakine benzer bir trick kullanıyoruz. sayfadaki ListView ın ViewCell_Appearing event i içerisinde, sayfaya bind etmiş olduğumuz model in içerisindeki, o anda ki satıra denk gelen model içerisinde ki fotoğraf sayısı kadar dönüp, bir image oluşturup flexlayou un Children property sine ekliyoruz. Gerisini resimde görmüş olduğunuz gibi kaç satır ve sütunda göstereceğine kendisi karar veriyor.
[XamlCompilation(XamlCompilationOptions.Compile)] public partial class FeedActivityView : ContentPage { FeedActivityViewModel viewModel; public FeedActivityView () { InitializeComponent (); NavigationPage.SetHasNavigationBar(this, false); viewModel = new FeedActivityViewModel(); BindingContext = viewModel; } private void ViewCell_Appearing(object sender, EventArgs e) { if (sender is ViewCell cell) { if (cell.BindingContext is FollowingItemModel viewModel) { var flexLayout = cell.FindByName("imagesLayout"); if (flexLayout?.Children.Count == 0 && viewModel.IamgeUrls.Count > 0) { foreach (var url in viewModel.IamgeUrls) { flexLayout.Children.Add(new Image { Source = new UriImageSource { Uri = new Uri(url), CacheValidity = TimeSpan.FromDays(1), CachingEnabled = true }, WidthRequest = 40, HeightRequest = 40, Margin = new Thickness { Left = 5, Bottom = 0, Right = 0, Top = 5}, Aspect = Aspect.AspectFill }); } } } } } }
Sayfanın backendinde başka bir numara yok. Viewmodel e baktığımızda ise durum şöyle;
public class FeedActivityViewModel : BaseViewModel { public FeedActivityViewModel() { FollowingItems = new ObservableCollection(); AboutYouItems = new ObservableCollection(); LoadFollowingItems(); LoadAboutYouItems(); GroupedItems = AboutYouItems.GroupBy(x => x.GroupName); LoadFollowingFeedListCommand = new Command(() => { LoadMoreActivity(); }); } private void LoadMoreActivity() { if (IsBusy) return; IsBusy = true; LoadFollowingItems(); IsBusy = false; } private void LoadFollowingItems() { FollowingItems.Add(new FollowingItemModel { Name = "Ian Dooley", ProfileUrl = "https://randomuser.me/api/portraits/women/41.jpg", IamgeUrls = new List { "https://images.unsplash.com/photo-1539608170043-f55d83afe1c9?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=89a54fa339be3dde93fa137a213655c7&auto=format&fit=crop&w=1189&q=80", "https://images.unsplash.com/photo-1539604880233-d282d9bac272?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=902aa0705d67ac390c0170c68aa4907f&auto=format&fit=crop&w=1051&q=80", "https://images.unsplash.com/photo-1539593608687-ccae798ff3ba?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=abbf25cb0a9e3f706263ff5fa81bf9d9&auto=format&fit=crop&w=1051&q=80" } }); FollowingItems.Add(new FollowingItemModel { Name = "Christian Becker", ProfileUrl = "https://randomuser.me/api/portraits/women/81.jpg", IamgeUrls = new List { "https://images.unsplash.com/photo-1539553521736-053bd7e14cf5?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=debb88414bb2ee774ce6229a72adac17&auto=format&fit=crop&w=500&q=60", "https://images.unsplash.com/photo-1539547018184-e5b1ce85fb07?ixlib=rb-0.3.5&s=1358c21c9ecdbbd65dd2993958ee4021&auto=format&fit=crop&w=500&q=60" } }); FollowingItems.Add(new FollowingItemModel { Name = "Velizer Ivanov", ProfileUrl = "https://randomuser.me/api/portraits/women/69.jpg", IamgeUrls = new List { "https://images.unsplash.com/photo-1539572996946-c0665d491f04?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=3ed5d83abf5f65bfae42fec7c5e44dd2&auto=format&fit=crop&w=500&q=60", "https://images.unsplash.com/photo-1539550298564-8a06769aa728?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=5a3cdac18faf595762d48ac529233dd3&auto=format&fit=crop&w=500&q=60", "https://images.unsplash.com/photo-1539546978801-fbee5d0fe203?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=1f2df90670dbf90177e118ff434fd708&auto=format&fit=crop&w=500&q=60", "https://images.unsplash.com/photo-1539546978801-fbee5d0fe203?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=1f2df90670dbf90177e118ff434fd708&auto=format&fit=crop&w=500&q=60", "https://images.unsplash.com/photo-1539547018184-e5b1ce85fb07?ixlib=rb-0.3.5&s=1358c21c9ecdbbd65dd2993958ee4021&auto=format&fit=crop&w=500&q=60", "https://images.unsplash.com/photo-1539608170043-f55d83afe1c9?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=89a54fa339be3dde93fa137a213655c7&auto=format&fit=crop&w=1189&q=80", "https://images.unsplash.com/photo-1539546978801-fbee5d0fe203?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=1f2df90670dbf90177e118ff434fd708&auto=format&fit=crop&w=500&q=60", } }); FollowingItems.Add(new FollowingItemModel { Name = "Sam Dawson", ProfileUrl = "https://randomuser.me/api/portraits/women/20.jpg", IamgeUrls = new List { "https://images.unsplash.com/photo-1539607547234-e09cdb14d473?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=ccf5de3e1f25a87315d6201723d67d26&auto=format&fit=crop&w=500&q=600" } }); FollowingItems.Add(new FollowingItemModel { Name = "Simon King", ProfileUrl = "https://randomuser.me/api/portraits/women/57.jpg", IamgeUrls = new List { "https://images.unsplash.com/photo-1539602783210-221ffbec8280?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=4b5bf2be9796a2d7b9b005a7cbf28372&auto=format&fit=crop&w=500&q=60" , "https://images.unsplash.com/photo-1539602783210-221ffbec8280?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=4b5bf2be9796a2d7b9b005a7cbf28372&auto=format&fit=crop&w=500&q=60", "https://images.unsplash.com/photo-1539602783210-221ffbec8280?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=4b5bf2be9796a2d7b9b005a7cbf28372&auto=format&fit=crop&w=500&q=60" } }); FollowingItems.Add(new FollowingItemModel { Name = "Ian Dooley", ProfileUrl = "https://randomuser.me/api/portraits/women/23.jpg", IamgeUrls = new List { "https://images.unsplash.com/photo-1539587310936-afda09bd0dc7?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=daf5f114d2545336bcab3e53bc4568e1&auto=format&fit=crop&w=500&q=60", "https://images.unsplash.com/photo-1539602010674-1346135ab34e?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=eb91750f2ad63d82661fb76b0772d6fd&auto=format&fit=crop&w=500&q=60", "https://images.unsplash.com/photo-1539585173613-89e3967da7d5?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=18ea6cc3988589adb75af4d8fe57d959&auto=format&fit=crop&w=500&q=60", "https://images.unsplash.com/photo-1539546978801-fbee5d0fe203?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=1f2df90670dbf90177e118ff434fd708&auto=format&fit=crop&w=500&q=60", "https://images.unsplash.com/photo-1539547018184-e5b1ce85fb07?ixlib=rb-0.3.5&s=1358c21c9ecdbbd65dd2993958ee4021&auto=format&fit=crop&w=500&q=60", "https://images.unsplash.com/photo-1539608170043-f55d83afe1c9?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=89a54fa339be3dde93fa137a213655c7&auto=format&fit=crop&w=1189&q=80", "https://images.unsplash.com/photo-1539546978801-fbee5d0fe203?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=1f2df90670dbf90177e118ff434fd708&auto=format&fit=crop&w=500&q=60", "https://images.unsplash.com/photo-1539546978801-fbee5d0fe203?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=1f2df90670dbf90177e118ff434fd708&auto=format&fit=crop&w=500&q=60", "https://images.unsplash.com/photo-1539547018184-e5b1ce85fb07?ixlib=rb-0.3.5&s=1358c21c9ecdbbd65dd2993958ee4021&auto=format&fit=crop&w=500&q=60", "https://images.unsplash.com/photo-1539608170043-f55d83afe1c9?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=89a54fa339be3dde93fa137a213655c7&auto=format&fit=crop&w=1189&q=80", "https://images.unsplash.com/photo-1539546978801-fbee5d0fe203?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=1f2df90670dbf90177e118ff434fd708&auto=format&fit=crop&w=500&q=60", "https://images.unsplash.com/photo-1539546978801-fbee5d0fe203?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=1f2df90670dbf90177e118ff434fd708&auto=format&fit=crop&w=500&q=60", "https://images.unsplash.com/photo-1539547018184-e5b1ce85fb07?ixlib=rb-0.3.5&s=1358c21c9ecdbbd65dd2993958ee4021&auto=format&fit=crop&w=500&q=60", "https://images.unsplash.com/photo-1539608170043-f55d83afe1c9?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=89a54fa339be3dde93fa137a213655c7&auto=format&fit=crop&w=1189&q=80", "https://images.unsplash.com/photo-1539546978801-fbee5d0fe203?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=1f2df90670dbf90177e118ff434fd708&auto=format&fit=crop&w=500&q=60",} }); FollowingItems.Add(new FollowingItemModel { Name = "Christian Becker", ProfileUrl = "https://randomuser.me/api/portraits/women/41.jpg", IamgeUrls = new List { "https://images.unsplash.com/photo-1539608170043-f55d83afe1c9?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=89a54fa339be3dde93fa137a213655c7&auto=format&fit=crop&w=1189&q=80", "https://images.unsplash.com/photo-1539604880233-d282d9bac272?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=902aa0705d67ac390c0170c68aa4907f&auto=format&fit=crop&w=1051&q=80", "https://images.unsplash.com/photo-1539593608687-ccae798ff3ba?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=abbf25cb0a9e3f706263ff5fa81bf9d9&auto=format&fit=crop&w=1051&q=80" } }); FollowingItems.Add(new FollowingItemModel { Name = "Sam Dawson", ProfileUrl = "https://randomuser.me/api/portraits/women/81.jpg", IamgeUrls = new List { "https://images.unsplash.com/photo-1539553521736-053bd7e14cf5?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=debb88414bb2ee774ce6229a72adac17&auto=format&fit=crop&w=500&q=60", "https://images.unsplash.com/photo-1539547018184-e5b1ce85fb07?ixlib=rb-0.3.5&s=1358c21c9ecdbbd65dd2993958ee4021&auto=format&fit=crop&w=500&q=60" } }); } private void LoadAboutYouItems() { AboutYouItems.Add(new FollowingItemModel { Name = "Ian Dooley", ProfileUrl = "https://randomuser.me/api/portraits/women/41.jpg", GroupName = "Yesterday" }); AboutYouItems.Add(new FollowingItemModel { Name = "Christian Becker", ProfileUrl = "https://randomuser.me/api/portraits/women/81.jpg", GroupName = "Yesterday" }); AboutYouItems.Add(new FollowingItemModel { Name = "Velizer Ivanov", ProfileUrl = "https://randomuser.me/api/portraits/women/69.jpg", GroupName = "Yesterday" }); AboutYouItems.Add(new FollowingItemModel { Name = "Sam Dawson", ProfileUrl = "https://randomuser.me/api/portraits/women/20.jpg", GroupName = "This Month" }); AboutYouItems.Add(new FollowingItemModel { Name = "Simon King", ProfileUrl = "https://randomuser.me/api/portraits/women/57.jpg", GroupName = "This Month" }); AboutYouItems.Add(new FollowingItemModel { Name = "Ian Dooley", ProfileUrl = "https://randomuser.me/api/portraits/women/23.jpg", GroupName = "This Month" }); AboutYouItems.Add(new FollowingItemModel { Name = "Christian Becker", ProfileUrl = "https://randomuser.me/api/portraits/women/41.jpg", GroupName = "This Month" }); AboutYouItems.Add(new FollowingItemModel { Name = "Sam Dawson", ProfileUrl = "https://randomuser.me/api/portraits/women/81.jpg", GroupName = "This Month" }); AboutYouItems.Add(new FollowingItemModel { Name = "Simon King", ProfileUrl = "https://randomuser.me/api/portraits/women/57.jpg", GroupName = "This Month" }); AboutYouItems.Add(new FollowingItemModel { Name = "Ian Dooley", ProfileUrl = "https://randomuser.me/api/portraits/women/23.jpg", GroupName = "This Month" }); AboutYouItems.Add(new FollowingItemModel { Name = "Christian Becker", ProfileUrl = "https://randomuser.me/api/portraits/women/41.jpg", GroupName = "This Month" }); AboutYouItems.Add(new FollowingItemModel { Name = "Sam Dawson", ProfileUrl = "https://randomuser.me/api/portraits/women/81.jpg", GroupName = "This Month" }); } public ObservableCollection<FollowingItemModel> FollowingItems { get; set; } public ObservableCollection<FollowingItemModel> AboutYouItems { get; set; } public IEnumerable<IGrouping<string, FollowingItemModel>> GroupedItems { get; set; } public ICommand LoadFollowingFeedListCommand { get; set; } } public class FollowingItemModel { public string GroupName { get; set; } public string Name { get; set; } public string ProfileUrl { get; set; } public List IamgeUrls { get; set; } }
FollowintItems ve AboutYouItems adında iki adet ObservableCollection ımız var. Bunların içerisi bize gruplu data gösterirken yardımcı olması adına oluşturduğumuz bir sınıf ile dolu. Bu sınıf FollowingItemModel . Yukarıdaki gibi porpertyleri var. Bu propertyleri listview grouplu bir şekilde kullanmak istediğimiz de ilgili alanlara bind etmemiz yeterli oluyor.
ItemsSource=”{Binding GroupedItems}”
IsGroupingEnabled=”True”
GroupDisplayBinding=”{Binding Key}”
gibi. Constructor tarafında da linq sorgusu ile
GroupedItems = AboutYouItems.GroupBy(x => x.GroupName);
diyerek follow tarafına basacağımız itemları gruplamış oluyoruz. bu şekilde karşımıza resimdeki gibi sectionlara ayrılmış bir listview çıkıyor.
Ek olarak sadece ListView refresh olduğunda çağırdımız bir command imiz var. Bu command de ObservableCollection larımızı dolduran metodlarımızı çağırıyor bu kadar.
Bir sonraki yazımda uygulamanın detayları için son kısımlara değineceğiz. Herhangi bir ekran daki açılan kapanan menüler istediğimizde bunu en kolay ve hızlı bir şekilde nasıl yaparız buna bakacağız.
Bir sonraki yazımda görüşmek üzere.