Özellik Bağlama (Property Bindings)

August 7, 2026 · View on GitHub

FmgLib.MauiMarkup, MAUI data binding'i her fluent özellik metodunda bulunan property builder lambda'sı (e => e…) ve tam kontrol için düşük seviyeli Bind() genişletmesi üzerinden sunar. Bağlanan kaynak değiştiğinde özellik güncellenir — XAML'deki {Binding} ile birebir aynı.

Builder Sözdizimi

Her özellik metodu, binding yapılandıran bir lambda kabul eder:

new Label().Text(e => e.Path("UserName"));

Builder metotları

MetotXAML karşılığıAçıklama
.Path(string)Path=Kaynaktaki özellik yolu. "." kaynağın kendisine bağlanır.
.Source(object)Source=Binding kaynağı; varsayılan, kontrolün BindingContext'idir.
.BindingMode(mode)Mode=OneWay, TwoWay, OneTime, OneWayToSource, Default.
.StringFormat(string)StringFormat=Sonuca uygulanan biçim dizesi.
.Converter(IValueConverter)Converter=Klasik converter örneği.
.Parameter(object)ConverterParameter=Converter'a iletilir.
.Convert<Q,R>(Func<Q,R>)Satır içi dönüştürme fonksiyonu (converter sınıfı gerekmez).
.ConvertBack<R,Q>(Func<R,Q>)Two-way binding'ler için ters dönüşüm.
.FallbackValue(object)FallbackValue=Binding çözülemediğinde kullanılır.
.TargetNullValue(object)TargetNullValue=Çözülen değer null olduğunda kullanılır.
.Getter(...) / .Setter(...)derlenmiş bindingExpression tabanlı — bkz. Derlenmiş Binding'ler.
Birden fazla .Path(...)MultiBinding.MultiConvert(...) ile birleştirilen çoklu kaynak — bkz. MultiBinding.
.Bindings(...)MultiBindingHazır alt binding nesneleri — bkz. MultiBinding.

BindingContext'e Bağlama (MVVM)

Varsayılan kaynak miras alınan BindingContext olduğundan, view-model'e bağlı bir sayfa doğal okunur:

public class ProfileViewModel : INotifyPropertyChanged
{
    public string UserName { get; set; } = "fmg";
    public string Email { get; set; } = "user@example.com";
    // ... PropertyChanged'i her zamanki gibi tetikleyin
}

public partial class ProfilePage : ContentPage, IFmgLibHotReload
{
    public ProfilePage() => this.InitializeHotReload();

    public void Build() =>
        this
        .BindingContext(new ProfileViewModel())
        .Content(
            new VerticalStackLayout()
            .Padding(20)
            .Children(
                new Label().Text(e => e.Path("UserName")).FontSize(28),
                new Label().Text(e => e.Path("Email")).TextColor(Colors.Gray),
                new Entry().Text(e => e.Path("UserName").BindingMode(BindingMode.TwoWay))
            )
        );
}

İç içe yollar, indeksleyiciler ve self yolu XAML'deki gibi çalışır:

.Text(e => e.Path("Address.City"))
.Text(e => e.Path("PhoneNumbers[0]"))
.Text(e => e.Path("."))                 // öğenin kendisi (şablonlarda yaygın)
.Text(e => e.Path("Text.Length"))       // özelliklerin alt özellikleri

Kontrolden Kontrole Bağlama

Kaynağı Assign ile yakalayıp .Source(...)'a verin:

new Slider().Assign(out var slider).Minimum(0).Maximum(100),

new Label()
    .Text(e => e.Path("Value").Source(slider).StringFormat("Value: {0:F0}"))

Two-way örnek — senkron bir Entry ve Label:

new Entry().Assign(out var input).Placeholder("Bir şeyler yazın"),
new Label().Text(e => e.Path("Text").Source(input))

FallbackValue ve TargetNullValue

new Label()
    .Text(e => e
        .Path("Employee.Name")
        .FallbackValue("(binding hatası)")   // yol çözülemedi
        .TargetNullValue("(isim yok)"))      // yol çözüldü, değer null

Düşük Seviyeli Bind() API'si

Her BindableObject, elinizde bir BindableProperty olduğunda kullanılan Bind(...) overload'larına da sahiptir. Attached property'ler veya yardımcı metotlar yazarken kullanışlıdır:

new SearchBar()
    .Assign(out var search)
    .SearchCommand(vm.SearchCommand)
    .Bind(SearchBar.SearchCommandParameterProperty, "Text", source: search)

Temel overload'un tam imzası:

public static T Bind<T>(this T self,
    BindableProperty targetProperty,
    string path = ".",
    BindingMode mode = BindingMode.Default,
    IValueConverter? converter = null,
    object? converterParameter = null,
    string? stringFormat = null,
    object? source = null,
    object? targetNullValue = null,
    object? fallbackValue = null) where T : BindableObject;

Generic overload'lar converter sınıfı yerine satır içi dönüştürme fonksiyonları kabul eder:

new Label()
    .Bind<Label, bool, Color>(Label.TextColorProperty, "IsError",
        convert: isError => isError ? Colors.Red : Colors.Black)

Çoklu kaynak overload'ları 2–4 binding'i value-tuple converter'la birleştirir (bkz. MultiBinding):

new Label()
    .Bind<Label, string, string, string>(Label.TextProperty,
        new Binding("FirstName"),
        new Binding("LastName"),
        convert: names => $"{names.Item1} {names.Item2}")

Diğer BindableObject yardımcıları

MetotAmaç
.BindingContext(object)BindingContext'i fluent ayarlar (context'in kendisini bağlamak için builder da alır).
.BindTemplatedParent(prop, path)RelativeBindingSource.TemplatedParent ile binding — ControlTemplate içerikleri için.
.AppThemeBinding(prop, light, dark)Rastgele bir BindableProperty için temaya bağlı değer.
.AppThemeColorBinding(prop, light, dark)Aynısı, Color için özelleştirilmiş.
.OnPropertyChanged(handler)PropertyChanged'e fluent abone olur.
.OnPropertyChanging(handler)PropertyChanging'e abone olur.
.OnBindingContextChanged(handler)BindingContextChanged'e abone olur.

Örnek — herhangi bir özellik değişimine tepki:

new Entry()
    .OnPropertyChanged(entry => Console.WriteLine($"{entry} üzerinde bir şey değişti"))

Şablonlarda Binding

Bir ItemTemplate içinde her gerçekleşen görünümün BindingContext'i öğedir; yalın Path çağrıları öğe özelliklerini hedefler:

new CollectionView()
.ItemsSource(e => e.Path("Products"))
.ItemTemplate(() =>
    new HorizontalStackLayout().Spacing(8).Children(
        new Label().Text(e => e.Path("Name")),
        new Label().Text(e => e.Path("Price").StringFormat("{0:C}"))
    )
)

Şablonun içinden sayfanın view model'ine bağlanmak Source kullanır:

public void Build()
{
    var vm = (CatalogViewModel)BindingContext;

    this.Content(
        new CollectionView()
        .ItemsSource(vm.Products)
        .ItemTemplate(() =>
            new Button()
                .Text("Sepete ekle")
                .Command(vm.AddToCartCommand)              // sayfa VM'i — doğrudan referans
                .Bind(Button.CommandParameterProperty, ".") // parametre olarak öğenin kendisi
        )
    );
}

Öneriler

  • View-model yolları için derlenmiş binding'leri (.Getter(...)) tercih edin — derleme zamanı kontrolü ve daha iyi performans.
  • Builder sözdizimini ham Bind()'e tercih edin; Bind()'e yalnızca attached BindableProperty hedefleri veya yeniden kullanılabilir yardımcılar için başvurun.
  • Hiç değişmeyecek değerleri bağlamayın — doğrudan değeri geçin (.Text(vm.Title) bir kez değerlendirilir) ve binding maliyetinden kaçının.

İlgili Konular