Xamarin.Forms’da Kaynak Sözlükleri | Resource Dictionaries
İçindekiler
Kaynak Sözlükleri XAML görünümlerini özelleştirmek için oluşturulan kaynakların deposudur. Bu kaynaklar arasında görünüm öğelerinin renkleri, kontrolleri, veri şablonları gibi özellikleri bulunur. Yani bir görünüm öğesini özelleştirmek istediğinizde bu kaynaklara başvurarak özelleştirmeler yapabilirsiniz.
Örneğin, kaynak sözlüklerine başvurarak uygulama içerisindeki tüm butonların aynı görünüme sahip olmasını ya da sadece bir XAML sayfasındaki Label’lerin aynı şablonda görünmesini sağlayabilirsiniz.
Çok sayıda görünüm elemanı içeren uygulamalarda her bir elemanı tek tek özelleştirmek yerine, uygulama düzeyinde kaynaklar oluşturup bunlara başvurmak daha iyi bir çözümdür.
XAML’da ResourceDictionary içinde tanımlanmış kaynaklara başvurabilir ve Dinamik veya Statik olarak öğelere uygulayabilirsiniz.
StaticResources, kaynakların görünüm öğelerine çalışma zamanında değişmeyecek şekilde uygulanmasıdır.
DynamicResources, kaynakların görünüm öğelerine çalışma zamanında değişebilecek şekilde uygulanmasıdır.
Kaynak Arama Davranışı Nasıl Gerçekleşir?
Bir Xamarin.Forms uygulamasında kaynak arama davranışı görsel ağaçta aşağıdaki sıraya göre gerçekleşir:
- İlk olarak özelliği ayarlanan öğe için aranan anahtar kaynak sözlüğünde varsa değeri döndürülür yoksa arama süreci sona erer.
- Eğer eşleşme bulunmadıysa arama işlemi görsel ağacı yukarı doğru arar ve her bir ana elemanın kaynak sözlüğünü kontrol eder. İstenen anahtar bulunursa değeri döndürülür yoksa arama süreci sona erer.
- Eğer kök öğede de bir eşleşme bulunmazsa uygulama düzeyinde kaynak sözlüğü incelenir.
- Hala bir eşleşme bulunmazsa, en sonunda bir XamlParseException atılır.
XAML’da Kaynak Sözlükleri Oluşturma
Kaynaklar, kaynak oluşturmak istediğiniz XAML öğesinde Resources içindeki Style ile oluşturulur. Style içerisinde TargetType ile kaynağın hangi tipteki öğeye uygulanacağını, x:Key ile de bu Style’e ait bir dize anahtarı tanımlayabilirsiniz. Örtük stiller haricinde, kaynak sözlüğündeki her kaynak, x:Key özniteliğiyle tanımlanan benzersiz bir dize anahtarına sahip olmalıdır.
Daha sonra Style içindeki Setter’lar ile de TargetType’ın property’lerine özelleştirmeler yapılır.
Kaynak sözlüklerini oluşturduğunuz yerler kaynakların nerede kullanılabileceğini etkiler.
- Kaynak denetimleri içindeki kaynakları Label, Button gibi belirli bir görünüm elemanına uygulayabilirsiniz.
- Ya da StackLayout veya Grid gibi belirli bir düzene ve bu düzenin alt öğelerine uygulayabilirsiniz.
- Sayfa düzeyindeki kaynak denetimleri ile bir sayfaya ve tüm alt öğelerine uygulayabilirsiniz.
- Uygulama düzeyindeki kaynak denetimleri içindeki kaynakları uygulama genelinde uygulayabilirsiniz.
Görünümlere Özel Kaynak Sözlükleri
XAML’da Button, Label gibi her bir görünüm elemanı için ayrı bir kaynak oluşturabilir ve uygulayabilirsiniz.
Görünüm düzeyinde kaynak oluşturmak için için görünüm elemanının tanımı içerisinde Resources altında Style tanımı yapın. Ardından TargetType ile bu kaynağı hangi türdeki XAML kontrolüne uygulamak istediğinizi belirtin.
Aşağıdaki kod parçasında StackLayout içerisindeki bir butona özel kaynağı görebilirsiniz. Bu kaynak sadece bu butonun görünümünü değiştireceği için kaynak denetimi eklenmemiş olan diğer buton Xamarin.Forms’un varsayılan görünümüne sahiptir.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Blog.Views.ViewResources">
<ContentPage.Content>
<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
<Button Text="BUTTON">
<Button.Resources>
<Style TargetType="Button">
<Setter Property="FontSize" Value="20" />
<Setter Property="BackgroundColor" Value="#eb5e0b" />
<Setter Property="TextColor" Value="#ffffff" />
<Setter Property="CornerRadius" Value="15" />
<Setter Property="WidthRequest" Value="200" />
<Setter Property="HeightRequest" Value="100" />
</Style>
</Button.Resources>
</Button>
<Button Text="BUTTON"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>

Düzene Özel Kaynak Sözlükleri
XAML’da Grid, StackLayout, AbsoluteLayout gibi düzenlere özel kaynak denetimleri oluşturabilirsiniz. Böylece oluşturduğunuz kaynaklar sadece o düzen içerisindeki görünüm öğelerini etkiler. Diğer düzenlerin içerisindeki görünümler Xamarin.Forms’un varsayılan değerleriyle görünür.
Düzene özel bir kaynak denetimi oluşturmak için o düzenin tanımı içerisinde Resources altında Style tanımı yapın. Ardından TargetType ile bu kaynağı hangi türdeki XAML kontrolüne uygulamak istediğinizi belirtin. Daha sonra x:Key özniteliği ile TargetType’a özel bir dize anahtarı ayarlayın. PrimaryButton, SecondaryButton gibi. Ardından bu anahtarı XAML öğesine verin.
Aşağıdaki kod parçasındaki ContentPage içerisinde iki tane Grid düzeni var.
Bunlardan üstteki Grid düzenine özel bir kaynak denetimi olduğu için ilk önce bu Grid yapısının içindeki butonlar kaynakta ayarlanmış değerlere göre görünür. Yani üstteki buton PrimaryButton x:Key özniteliğine sahip olduğu için bu özniteliğe sahip olan değerlere göre görünürken, alttaki buton ise SecondaryButton x:Key özniteliğine sahip olduğu için bu özniteliğe sahip olan değerlere göre görünür.
Diğer Grid düzenine özel bir kaynak olmadığı için bu Grid içindeki butonlar Xamarin.Forms’un varsayılan Button görünümüne sahiptir.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Blog.Views.LayoutResources">
<ContentPage.Content>
<StackLayout VerticalOptions="Center" HorizontalOptions="Center">
<Grid>
<Grid.Resources>
<Style x:Key="PrimaryButton" TargetType="Button">
<Setter Property="FontSize" Value="20" />
<Setter Property="BackgroundColor" Value="#eb5e0b" />
<Setter Property="TextColor" Value="#ffffff" />
<Setter Property="CornerRadius" Value="15" />
<Setter Property="WidthRequest" Value="100" />
<Setter Property="HeightRequest" Value="100" />
</Style>
<Style x:Key="SecondaryButton" TargetType="Button">
<Setter Property="FontSize" Value="20" />
<Setter Property="BackgroundColor" Value="#314e52" />
<Setter Property="TextColor" Value="#ffffff" />
<Setter Property="CornerRadius" Value="15" />
<Setter Property="WidthRequest" Value="100" />
<Setter Property="HeightRequest" Value="100" />
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Button Text="BUTTON" Style="{StaticResource PrimaryButton}" Grid.Row="0"/>
<Button Text="BUTTON" Style="{StaticResource SecondaryButton}" Grid.Row="1"/>
</Grid>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Button Text="BUTTON" Grid.Row="0"/>
<Button Text="BUTTON" Grid.Row="1"/>
<Button Text="BUTTON" Grid.Row="2"/>
</Grid>
</StackLayout>
</ContentPage.Content>
</ContentPage>

Sayfa Düzeyinde Kaynak Sözlükleri
XAML’da ContentPage, NavigationPage, TabbedPage gibi sayfalara özel kaynak denetimleri oluşturabilirsiniz. Böylece oluşturduğunuz kaynaklar sadece o sayfa içerisindeki görünüm öğelerini etkiler. Diğer sayfaların içerisindeki görünümler Xamarin.Forms’un varsayılan değerleriyle görünür.
Sayfa düzeyinde kaynak oluşturmak için için sayfanın tanımı içerisinde Resources altında Style tanımı yapın. Ardından TargetType ile bu kaynağı hangi türdeki XAML kontrolüne uygulamak istediğinizi belirtin. Daha sonra dilerseniz x:Key özniteliği ile TargetType’a özel bir dize anahtarı tanımlayıp sonra bu anahtarı ilgili XAML öğesine ayarlayabilirsiniz.
Aşağıdaki kod parçasında ContentPage’ye özel bir kaynak denetimini görebilirsiniz. Bu kaynak sadece bu sayfanın Button ve Label görünümlerine özel olduğu için kaynak denetimi eklenmemiş olan diğer görünüm öğeleri Xamarin.Forms’un varsayılan görünümüne sahiptir. Ayrıca bu sayfadaki kaynaklar başka bir ContentPage içerisindeki görünüm elemanlarını etkilemez.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Blog.Views.PageResources">
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="Button">
<Setter Property="FontSize" Value="20" />
<Setter Property="BackgroundColor" Value="#eb5e0b" />
<Setter Property="TextColor" Value="#ffffff" />
<Setter Property="CornerRadius" Value="15" />
<Setter Property="WidthRequest" Value="100" />
<Setter Property="HeightRequest" Value="100" />
</Style>
<Style TargetType="Label">
<Setter Property="BackgroundColor" Value="Pink"/>
<Setter Property="FontSize" Value="24"/>
<Setter Property="FontAttributes" Value="Bold"/>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
<Label Text="Welcome to Xamarin.Forms!"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" />
<Button Text="BUTTON" />
<Button Text="BUTTON" />
<Button Text="BUTTON" />
</StackLayout>
</ContentPage.Content>
</ContentPage>

Uygulama Düzeyinde Kaynak Sözlükleri
Xamarin.Forms’da uygulama düzeyinde bir kaynak denetimi oluşturarak özelleştirmelerinizin tüm XAML görünümlerinde geçerli olmasını sağlayabilirsiniz. Böylece herhangi bir XAML öğesine ya da sayfaya özel kaynaklar oluşturmanıza gerek kalmaz.
Uygulama düzeyinde bir kaynak denetimi eklemek için aşağıdaki adımları sırasıyla uygulayın.
1) Bağımsız (stand-alone) kaynak denetimleri oluşturun
Bağımsız kaynak denetimleri ResourceDictionary sınıfından miras alan, tek başına bir XAML dosyasıdır. Bu XAML dosyaları diğer XAML dosyaları gibi daha sonra uygulama içerisinde kullanılabilir.
Ben bu örnek proje için DarkTheme.xaml adında bir kaynak oluşturup daha sonra bu kaynağı App.xaml’da çağıracağım.
1 İlk olarak, Xamarin.Forms projenize bir ContentPage ya da ContentView ekleyin. Ben bu örnek projeye DarkTheme.xaml adında bir ContentPage ekledim.
2 Daha sonra oluşturduğunuz XAML dosyasının kod tarafına gidin ve bu sayfanın ResourceDictionary sınıfından miras almasını sağlayın. Ben DarkTheme.xaml.cs sınıfında bu değişikliği yaptım.
public partial class DarkTheme : ResourceDictionary
{
public DarkTheme()
{
InitializeComponent();
}
}
3 Ardından eklediğiniz XAML sayfasına gidin ve ContentPage tanımını ResourceDictionary ile değiştirin. Böylece kod tarafında yaptığınız değişikliğin aynısını XAML’da yapmış olacaksınız.
Son olarak ResourceDictionary içerisine kaynaklarınızı ekleyin.
<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Blog.DarkTheme">
<Color x:Key="PageBackgroundColor">Black</Color>
<Color x:Key="NavigationBarColor">Teal</Color>
<Color x:Key="PrimaryColor">Pink</Color>
<Color x:Key="SecondaryColor">White</Color>
<Color x:Key="PrimaryTextColor">White</Color>
<Color x:Key="SecondaryTextColor">White</Color>
<Color x:Key="TertiaryTextColor">WhiteSmoke</Color>
<Color x:Key="TransparentColor">Transparent</Color>
</ResourceDictionary>
Ben DarkTheme.xaml içerisinde sadece karanlık tema için renk tanımları yaptım. Siz dilediğiniz sayıda bağımsız kaynak denetimleri oluşturabilir ve kaynaklar ekleyebilirsiniz.
2) App.xaml içerisinde kaynaklarınızı tanımlayın
Bağımsız kaynak denetimlerini oluşturduktan sonra bağımsız kaynakları App.xaml içerisindeki kaynaklarda çağırmalısınız.
Ayrıca App.xaml içerisindeki kaynaklara XAML görünüm öğeleri için de kaynaklar oluşturabilirsiniz. Böylece hedef öğeleriniz için uyguladığınız özelleştirmeler uygulama genelinde geçerli olacak.
App.xaml kodları
<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Blog.App">
<Application.Resources>
<!--<ResourceDictionary Source="DarkTheme.xaml" />-->
<!-- Colors -->
<Color x:Key="BackgroundColor">#c7ffd8</Color>
<Color x:Key="PrimaryColor">#493323</Color>
<Color x:Key="SecondaryColor">#314e52</Color>
<Color x:Key="TextColor">#ffe227</Color>
<!-- Implicit styles -->
<Style TargetType="{x:Type ContentPage}">
<Setter Property="BackgroundColor" Value="{StaticResource BackgroundColor}" />
</Style>
<Style TargetType="{x:Type Button}">
<Setter Property="BackgroundColor" Value="{StaticResource PrimaryColor}"/>
<Setter Property="TextColor" Value="{StaticResource TextColor}"/>
<Setter Property="HorizontalOptions" Value="Center"/>
<Setter Property="VerticalOptions" Value="Center"/>
<Setter Property="CornerRadius" Value="10"/>
</Style>
<Style TargetType="{x:Type Label}">
<Setter Property="FontSize" Value="32" />
<Setter Property="BackgroundColor" Value="{StaticResource SecondaryColor}" />
<Setter Property="TextColor" Value="{StaticResource TextColor}" />
</Style>
</Application.Resources>
</Application>
ContentPage kodları
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Blog.Views.ResourceDictionaryPage"
BackgroundColor="{StaticResource BackgroundColor}">
<ContentPage.Content>
<StackLayout VerticalOptions="Center" HorizontalOptions="Center">
<Button Text="BUTTON"/>
<Button Text="BUTTON"/>
<Label Text="LABEL" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
