Kullanıcı Tanımlı Genişletme Metotları
FmgLib.MauiMarkup'ı kendi fluent metotlarınızla genişletebilirsiniz — ya mevcut metotlardan kurulan anlamsal kısayollar, ya da yerleşiklerle birebir aynı şekilde binding'lere, stillere ve animasyonlara katılan tam özellik metotları.
Seviye 1 — Kompozisyon Kısayolları#
En basit ve en yararlı tür: tekrar eden zincirleri statik bir metotta sarın. Kütüphane makinesine gerek yok, çünkü her fluent metot T döndürür:
public static class MarkupHelpers
{
public static T PrimaryText<T>(this T self) where T : Label
=> self.FontSize(16).TextColor(AppColors.TextPrimary).FontFamily("OpenSansRegular");
public static T Card<T>(this T self) where T : Border
=> self
.BackgroundColor(e => e.OnLight(Colors.White).OnDark("#1E1E2E".ToColor()))
.StrokeThickness(0)
.Padding(16)
.Shadow(new Shadow().Radius(10).Opacity(0.15f));
}
// kullanım:
new Label().Text("Toplam").PrimaryText()
new Border().Card().Content(/* ... */)
Somut tipin zincir boyunca akması için <T> generic + where T : ... kısıt desenini koruyun.
Seviye 2 — Tam Özellik Metotları (dört overload şablonu)#
Bir özelliğin native FmgLib özelliği gibi davranması için — doğrudan değerleri, builder lambda'sını (binding'ler, OnLight/OnDark, DynamicResource…) ve stilleri desteklemesi için — dört standart overload'u uygulayın. İşte Label.FontSize için tam şablon (generator'ın ürettiğinin aynısı):
public static class MyLabelExtensions
{
// 1. Doğrudan değer
public static T FontSize<T>(this T self, double fontSize)
where T : Microsoft.Maui.Controls.Label
{
self.SetValue(Microsoft.Maui.Controls.Label.FontSizeProperty, fontSize);
return self;
}
// 2. Property builder — e.Path(...), e.OnLight(...), e.DynamicResource(...) vb. sağlar
public static T FontSize<T>(this T self,
Func<PropertyContext<double>, IPropertyBuilder<double>> configure)
where T : Microsoft.Maui.Controls.Label
{
var context = new PropertyContext<double>(self, Microsoft.Maui.Controls.Label.FontSizeProperty);
configure(context).Build();
return self;
}
// 3. Stil setter'ı
public static SettersContext<T> FontSize<T>(this SettersContext<T> self, double fontSize)
where T : Microsoft.Maui.Controls.Label
{
self.XamlSetters.Add(new Setter
{
Property = Microsoft.Maui.Controls.Label.FontSizeProperty,
Value = fontSize
});
return self;
}
// 4. Builder'lı stil setter'ı
public static SettersContext<T> FontSize<T>(this SettersContext<T> self,
Func<PropertySettersContext<double>, IPropertySettersBuilder<double>> configure)
where T : Microsoft.Maui.Controls.Label
{
var context = new PropertySettersContext<double>(self.XamlSetters,
Microsoft.Maui.Controls.Label.FontSizeProperty);
configure(context).Build();
return self;
}
}
Bileşenler:
PropertyContext<TValue>— kontrolüBindablePropertyile eşler; lambda'nızın döndürdüğü builder onu nasıl bağlayacağını/ayarlayacağını bilir.SettersContext<T>— birStyle<T>tanımı içindekiSetter'ları toplar.- Stiller/binding'ler/trigger'lar çalışmaya devam etsin diye her zaman
BindableProperty'yiSetValueile hedefleyin (CLR özelliğini değil).
Dördü de yerinde olunca her kullanım deseni aktifleşir:
new Label().FontSize(28); // değer
new Label().FontSize(e => e.Path("MyFontSize").Source(myModel)); // binding
new Label().FontSize(e => e.OnPhone(30).OnTablet(50).Default(40)); // idiom
new Style<Label>(e => e.FontSize(20).CenterVertically()); // stil
Seviye 3 — Animasyon Yardımcıları#
Özelliğiniz için kütüphanenin Transformations yardımcısıyla bir Animate…To ekleyin (bkz. Animasyonlar):
public static Task<bool> AnimateFontSizeTo<T>(this T self, double value,
uint length = 250, Easing? easing = null)
where T : Microsoft.Maui.Controls.Label
{
double fromValue = self.FontSize;
var transform = (double t) => Transformations.DoubleTransform(fromValue, value, t);
var callback = (double actValue) => { self.FontSize = actValue; };
return Transformations.AnimateAsync<double>(self, "AnimateFontSizeTo", transform, callback, length, easing);
}
await titleLabel.AnimateFontSizeTo(40, 300, Easing.CubicOut);
Manuel Genişletme mi, Generator mı?#
| Durum | Yaklaşım |
|---|---|
BindableProperty/olaylı üçüncü parti kontrol |
[MauiMarkup(typeof(...))] — generator tüm overload'ları yazar |
Kendi BindableObject kontrolünüz |
Yine generator — uygulama projesinden işaretleyin |
Düz CLR özelliği (BindableProperty yok) |
Manuel genişletme (yalnızca 1. şekil anlamlı — BindableProperty olmadan binding desteği yok) |
Tasarım-sistemi kısayolları (PrimaryText, Card) |
Seviye 1 kompozisyon |
Çok özellikli kolaylık (SizeRequest tarzı) |
Seviye 1 kompozisyon |
| Özel animasyonlar | Seviye 3 |
Tasarım İpuçları#
- Aksiyonu değil, özelliği adlandırın:
CornerRadius(8),SetCornerRadius(8)değil — API'nin geri kalanıyla tutarlılık. - Paylaşılan yardımcıları kontrol ailesi başına özel statik sınıflara koyun (
LabelHelpers,LayoutHelpers); ekstrausingolmadan görünmelerini istiyorsanıznamespace FmgLib.MauiMarkupbloğunun içine — veya netlik için kendi ad alanınızda tutun. T(generic) döndürün, somut taban tipini asla — yoksa türemiş kontroller için zincirleri kırarsınız.
İlgili Konular#
- Fluent Özellikler — overload sözleşmesi
- Üçüncü Parti Kontroller — bu işi generator'a yaptırmak
- Animasyonlar