Özel bağımlılık özellikleri (WPF .NET)

Windows Presentation Foundation (WPF) uygulama geliştiricileri ve bileşen yazarları, özelliklerinin işlevselliğini genişletmek için özel bağımlılık özellikleri oluşturabilir. Ortak dil çalışma zamanı (CLR) özelliğinin aksine, bağımlılık özelliği stil oluşturma, veri bağlama, devralma, animasyonlar ve varsayılan değerler için destek ekler. Background, Width ve Text , WPF sınıflarında mevcut bağımlılık özelliklerine örnek olarak verilmiştir. Bu makalede özel bağımlılık özelliklerinin nasıl uygulanacakları açıklanmıştır ve performansı, kullanılabilirliği ve çok yönlülüğü geliştirmeye yönelik seçenekler sunulmaktadır.

Önemli

.NET 6 ve .NET 5 için Masaüstü Kılavuzu belgeleri (.NET Core 3.1 dahil) hazır aşamasındadır.

Önkoşullar

Makalede, bağımlılık özellikleriyle ilgili temel bilgiler olduğu ve Bağımlılık özelliklerine genel bakış makalesine bakabilirsiniz. Bu makaledeki örnekleri takip etmek için, Extensible Application Markup Language (XAML) ve WPF uygulamaları yazmayı biliyorsanız yardımcı olur.

Bağımlılık özelliği tanımlayıcısı

Bağımlılık özellikleri, veya çağrıları aracılığıyla WPF özellik sistemine kayıtlı RegisterRegisterReadOnly özelliklerdir. yöntemi, Register bir DependencyProperty bağımlılık özelliğinin kayıtlı adını ve özelliklerini tutan bir örnek döndürür. Örneği, kurala göre olarak adlandırılmış bir bağımlılık özelliği tanımlayıcısı olarak bilinen statik salt DependencyProperty okunur alanına DependencyPropertyatarsiniz. <property name>Property Örneğin, özelliğin tanımlayıcı alanı her Background zaman BackgroundProperty olur.

Bağımlılık özelliği tanımlayıcısı, özel bir alan ile bir özelliğin destek standart deseni yerine özellik değerlerini almak veya ayarlamaya yönelik bir destek alanı olarak kullanılır. Özellik sistemi tanımlayıcıyı kullanır, XAML işlemcileri bunu kullanabilir ve kodunuz (ve muhtemelen dış kod), tanımlayıcıları aracılığıyla bağımlılık özelliklerine erişebilirsiniz.

Bağımlılık özellikleri yalnızca türlerden türetilen sınıflara DependencyObject uygulanabilir. WPF sınıf hiyerarşisinin köküne yakın olduğundan çoğu WPF sınıfı bağımlılık DependencyObject özelliklerini destekler. Bağımlılık özellikleri ve bunları açıklamak için kullanılan terminoloji ve kuralları hakkında daha fazla bilgi için bkz. Bağımlılık özelliklerine genel bakış.

Bağımlılık özelliği sarmalayıcıları

Ekli olmayan WPF bağımlılık özellikleri, ve erişimcileri uygulayan bir CLR sarmalayıcı get tarafından set ortaya çıkar. Özellik sarmalayıcı kullanarak, bağımlılık özelliklerinin tüketicileri diğer CLR özellikleri gibi bağımlılık özellik değerlerini de elde eder veya ayarlar. ve erişimcileri, bağımlılık özelliği tanımlayıcısını parametre olarak geçirme yoluyla ve çağrıları getset aracılığıyla temel özellik DependencyObject.GetValueDependencyObject.SetValue sistemiyle etkileşime geçer. Bağımlılık özelliklerinin tüketicileri genellikle veya doğrudan çağırmaz, ancak özel bir bağımlılık özelliği uygulayıyorsanız bu yöntemleri sarmalayıcıda GetValueSetValue kullanacağız.

Bağımlılık özelliği ne zaman uygulanır?

sınıfından türeten bir sınıfa bir özellik uygulayan, bir tanımlayıcı ile özelliğinizi destekleerek bunu DependencyObject bir bağımlılık özelliği DependencyProperty yapmak. Bağımlılık özelliği oluşturmanın yararlı olup olmadığı senaryona bağlıdır. Özelliğinizi özel bir alanla desteklemek bazı senaryolar için yeterli olsa da, özelliğinizin aşağıdaki WPF özelliklerinden birini veya daha fazlasını desteklemesi için bir bağımlılık özelliği uygulamayı göz önünde bulundurabilirsiniz:

  • Stil içinde ayarlanamayan özellikler. Daha fazla bilgi için bkz. Stiller ve şablonlar.

  • Veri bağlamayı destekleyen özellikler. Veri bağlama bağımlılık özellikleri hakkında daha fazla bilgi için bkz. İki denetimin özelliklerini bağlama.

  • Dinamik kaynak başvuruları aracılığıyla ayarlanamayan özellikler. Daha fazla bilgi için bkz. XAML kaynakları.

  • Öğe ağacında bir üst öğeden otomatik olarak kendi değerini devralan özellikler. Bunun için, CLR erişimi için bir özellik sarmalayıcı da oluştursanız bile kullanarak RegisterAttached kaydolmanız gerekir. Daha fazla bilgi için bkz. Özellik değeri devralma.

  • Animasyona animasyon özelliği olan özellikler. Daha fazla bilgi için bkz. Animasyona genel bakış.

  • Bir özellik değeri değişirse WPF özellik sistemi tarafından bildirim. Değişiklikler özellik sistemi, ortam, kullanıcı veya stiller tarafından yapılan eylemlerden dolayı olabilir. Özelliğiniz özellik meta verilerinde özellik sistemi özellik değerinizin değiştirdiğini her belirlerken çağrılan bir geri çağırma yöntemi belirtebilirsiniz. İlgili kavram, özellik değeri zorlamasıdır. Daha fazla bilgi için bkz. Bağımlılık özelliği geri çağırmaları ve doğrulaması.

  • WPF işlemleri tarafından okunan bağımlılık özelliği meta verilerine erişim. Örneğin, özellik meta verilerini kullanarak şunları sabilirsiniz:

    • Değiştirilen bağımlılık özelliği değerinin düzen sisteminin bir öğe için görselleri yeniden derlemesi gerekip gerek olmadığını belirtin.

    • Türetilmiş sınıflarda meta verileri geçersiz karak bağımlılık özelliğinin varsayılan değerini ayarlayın.

  • Visual Studio penceresinde özel bir denetimin özelliklerini düzenleme gibi bir WPF tasarımcısı desteği sağlar. Daha fazla bilgi için bkz. Denetim yazmaya genel bakış.

Bazı senaryolarda, mevcut bağımlılık özelliğinin meta verilerini geçersiz kılma, yeni bir bağımlılık özelliği uygulamaya göre daha iyi bir seçenektir. Meta veri geçersiz kılmanın pratik olup olmadığı senaryoya bağlıdır ve bu senaryonun mevcut WPF bağımlılık özellikleri ve sınıflarının uygulanmasına ne kadar yakından benzemektedir. Mevcut bağımlılık özelliklerine meta verileri geçersiz kılma hakkında daha fazla bilgi için bkz. Bağımlılık özelliği meta verileri.

Bağımlılık özelliği oluşturmak için denetim listesi

Bağımlılık özelliği oluşturmak için bu adımları izleyin. Adımlardan bazıları tek bir kod satırı içinde bir araya toplanır ve uygulanır.

  1. (İsteğe bağlı) Bağımlılık özelliği meta verileri oluşturun.

  2. Özellik adı, sahip türü, özellik değeri türü ve isteğe bağlı olarak özellik meta verileri belirterek bağımlılık özelliğini özellik sistemine kaydetme.

  3. Tanımlayıcıyı DependencyProperty sahip public static readonly türünde bir alan olarak tanımlayın. Tanımlayıcı alanı adı, son ekin ekli olduğu özellik Property adıdır.

  4. Bağımlılık özelliği adıyla aynı adla bir CLR sarmalayıcı özelliği tanımlayın. CLR sarmalayıcıda, getset sarmalayıcıyı geri alan bağımlılık özelliğiyle bağlantı yapan ve erişimcilerini uygulama.

Özelliği kaydetme

Özelliğinizin bağımlılık özelliği olması için özellik sistemine kaydetmeniz gerekir. Özelliğinizi kaydetmek için yöntemini sınıf gövdesinin içinden ancak üye Register tanımlarının dışından çağırabilirsiniz. yöntemi, Register özellik sistemi API'sini çağırarak kullanabileceğiniz benzersiz bir bağımlılık özellik tanımlayıcısı döndürür. Çağrının üye tanımlarının dışında yapılmış bir nedeni, dönüş değerini türünde Register bir alana public static readonlyDependencyProperty atamadır. Sınıfınıza oluşturacak olan bu alan, bağımlılık özelliğinizin tanımlayıcısıdır. Aşağıdaki örnekte, ilk bağımsız değişkeni bağımlılık Register özelliğini olarak AquariumGraphic adlar.

// Register a dependency property with the specified property name,
// property type, owner type, and property metadata. Store the dependency
// property identifier as a public static readonly member of the class.
public static readonly DependencyProperty AquariumGraphicProperty =
    DependencyProperty.Register(
      name: "AquariumGraphic",
      propertyType: typeof(Uri),
      ownerType: typeof(Aquarium),
      typeMetadata: new FrameworkPropertyMetadata(
          defaultValue: new Uri("http://www.contoso.com/aquarium-graphic.jpg"),
          flags: FrameworkPropertyMetadataOptions.AffectsRender,
          propertyChangedCallback: new PropertyChangedCallback(OnUriChanged))
    );
' Register a dependency property with the specified property name,
' property type, owner type, and property metadata. Store the dependency
' property identifier as a public static readonly member of the class.
Public Shared ReadOnly AquariumGraphicProperty As DependencyProperty =
    DependencyProperty.Register(
        name:="AquariumGraphic",
        propertyType:=GetType(Uri),
        ownerType:=GetType(Aquarium),
        typeMetadata:=New FrameworkPropertyMetadata(
            defaultValue:=New Uri("http://www.contoso.com/aquarium-graphic.jpg"),
            flags:=FrameworkPropertyMetadataOptions.AffectsRender,
            propertyChangedCallback:=New PropertyChangedCallback(AddressOf OnUriChanged)))

Not

Sınıf gövdesinde bağımlılık özelliğini tanımlamak tipik bir uygulamadır, ancak sınıf statik oluşturucusu içinde bir bağımlılık özelliği tanımlamak da mümkündür. Bağımlılık özelliğini başlatmak için birden fazla kod satırına ihtiyacınız varsa bu yaklaşım mantıklı olabilir.

Bağımlılık özelliği adlandırması

Bağımlılık özellikleri için kurulan adlandırma kuralı, özellik sisteminin normal davranışı için zorunludur. Oluşturmakta olduğu tanımlayıcı alanı adı, son eke sahip özelliğin kayıtlı adı Property olmalıdır.

Bağımlılık özelliği adı, kayıt sınıfında benzersiz olmalıdır. Temel tür aracılığıyla devralınan bağımlılık özellikleri zaten kaydedilmiştir ve türetilmiş bir tür tarafından kaydedilenem edilemez. Ancak, sınıfını bağımlılık özelliğinin sahibi olarak ekleyerek sınıfını devralınmayacak bir tür bile olsa, farklı bir tür tarafından kaydedilmiş bir bağımlılık özelliğini kullanabilirsiniz. Sahip olarak sınıf ekleme hakkında daha fazla bilgi için bkz. Bağımlılık özelliği meta verileri.

Özellik sarmalayıcı uygulama

Kural gereği sarmalayıcı özelliğinin adı, bağımlılık özelliği adı olan Register çağrının ilk parametresiyle aynı olmalıdır. Sarmalayıcı uygulamanız GetValue erişimcide get ve erişimcide SetValueset (okuma-yazma özellikleri için) çağrısını alır. Aşağıdaki örnek, kayıt çağrısı ve tanımlayıcı alanı bildiriminin ardından bir sarmalayıcı gösterir. WPF sınıflarında tüm genel bağımlılık özellikleri benzer bir sarmalayıcı modeli kullanır.

// Register a dependency property with the specified property name,
// property type, owner type, and property metadata. Store the dependency
// property identifier as a public static readonly member of the class.
public static readonly DependencyProperty AquariumGraphicProperty =
    DependencyProperty.Register(
      name: "AquariumGraphic",
      propertyType: typeof(Uri),
      ownerType: typeof(Aquarium),
      typeMetadata: new FrameworkPropertyMetadata(
          defaultValue: new Uri("http://www.contoso.com/aquarium-graphic.jpg"),
          flags: FrameworkPropertyMetadataOptions.AffectsRender,
          propertyChangedCallback: new PropertyChangedCallback(OnUriChanged))
    );

// Declare a read-write property wrapper.
public Uri AquariumGraphic
{
    get => (Uri)GetValue(AquariumGraphicProperty);
    set => SetValue(AquariumGraphicProperty, value);
}
' Register a dependency property with the specified property name,
' property type, owner type, and property metadata. Store the dependency
' property identifier as a public static readonly member of the class.
Public Shared ReadOnly AquariumGraphicProperty As DependencyProperty =
    DependencyProperty.Register(
        name:="AquariumGraphic",
        propertyType:=GetType(Uri),
        ownerType:=GetType(Aquarium),
        typeMetadata:=New FrameworkPropertyMetadata(
            defaultValue:=New Uri("http://www.contoso.com/aquarium-graphic.jpg"),
            flags:=FrameworkPropertyMetadataOptions.AffectsRender,
            propertyChangedCallback:=New PropertyChangedCallback(AddressOf OnUriChanged)))

' Declare a read-write property wrapper.
Public Property AquariumGraphic As Uri
    Get
        Return CType(GetValue(AquariumGraphicProperty), Uri)
    End Get
    Set
        SetValue(AquariumGraphicProperty, Value)
    End Set
End Property

Nadir durumlar dışında, sarmalayıcı uygulamanız yalnızca ve kodunu GetValueSetValue içermeli. Bunun ardındaki nedenler için bkz. Özel bağımlılık özellikleri için etkileri.

Özelliğiniz, kurulan adlandırma kurallarına uymazsa şu sorunlar ile karşınıza çıktı:

  • Stillerin ve şablonların bazı yönleri çalışmaz.

  • Çoğu araç ve tasarımcı, XAML'i düzgün bir şekilde seri hale getirme ve özellik başına tasarımcı ortamı yardımı sağlamak için adlandırma kurallarına güvenmektedir.

  • WPF XAML yükleyicinin geçerli uygulaması sarmalayıcıları tamamen atlar ve öznitelik değerlerini işleme adlandırma kuralına bağlı olur. Daha fazla bilgi için bkz. XAML yükleme ve bağımlılık özellikleri.

Bağımlılık özelliği meta verileri

Bir bağımlılık özelliğini kaydedtiğiniz zaman, özellik sistemi özellik özelliklerini depolamak için bir meta veri nesnesi oluşturur. yönteminin aşırı Register yüklemeleri kayıt sırasında özellik meta verilerini belirtmenize izin verir, örneğin Register(String, Type, Type, PropertyMetadata) . Özellik meta verilerinde yaygın olarak kullanılan bir kullanım, bağımlılık özelliği kullanan yeni örnekler için özel bir varsayılan değer uygulamaktır. Özellik meta verileri sağlanmayacaksa, özellik sistemi bağımlılık özelliği özelliklerinin çoğuna varsayılan değerler atar.

sınıfından türetilen bir sınıfta bağımlılık özelliği oluşturuyorsanız, temel sınıfı yerine daha özelleştirilmiş meta FrameworkElementFrameworkPropertyMetadata veri sınıfını PropertyMetadata kullanabilirsiniz. Çeşitli FrameworkPropertyMetadata oluşturucu imzaları, meta veri özelliklerinin farklı birleşimlerini belirtmenize izin verir. Yalnızca varsayılan bir değer belirtmek için kullanın ve FrameworkPropertyMetadata(Object) varsayılan değeri parametresine Object iletirsiniz. Değer türünün çağrıda belirtilen değerle propertyType eş olduğundan emin Register olur.

Bazı FrameworkPropertyMetadata aşırı yüklemeler özelliğiniz FrameworkPropertyMetadata belirtmenize izin verir. Özellik sistemi bu bayrakları ayrık özelliklere dönüştürür ve bayrak değerleri düzen altyapısı gibi WPF işlemleri tarafından kullanılır.

Meta veri bayraklarını ayarlama

Meta veri bayraklarını ayarlarken şunları göz önünde önünde ekleyin:

  • Özellik değeriniz (veya üzerinde yaptığınız değişiklikler) düzen sisteminin bir kullanıcı arabirimi öğesini nasıl işleyeceğini etkiliyorsa, aşağıdaki bayraklardan birini veya daha fazlasını ayarlayın:

    • AffectsMeasure, özellik değerindeki bir değişikliğin, özellikle üst öğesi içindeki bir nesne tarafından kapladığı alan olmak üzere kullanıcı arabirimi işlemesinde bir değişiklik gerektirdiğini gösterir. Örneğin, bir özellik için bu meta veri bayrağını Width ayarlayın.

    • AffectsArrange, özellik değerindeki bir değişikliğin kullanıcı arabirimi işlemesinde, özellikle bir nesnenin üst öğesi içindeki konumunun değişmesini gerektirdiğini gösterir. Genellikle nesne boyutunu da değiştirmez. Örneğin, bir özellik için bu meta veri bayrağını Alignment ayarlayın.

    • AffectsRender, düzeni ve ölçümü etkilemeden başka bir işleme gerektiren bir değişiklik olduğunu gösterir. Örneğin, bu bayrağı bir özellik Background veya bir öğenin rengini etkileyen başka bir özellik için ayarlayın.

    Bu bayrakları özellik sistemi (veya düzen) geri çağırmalarının geçersiz kılma uygulamalarınıza giriş olarak da kullanabilirsiniz. Örneğin, örneğin bir özelliği bir değer değişikliği raporlasa ve meta verilerde ayarlanmışsa çağrısı yapmak için OnPropertyChangedInvalidateArrange bir geri çağırma AffectsArrange kullanabilirsiniz.

  • Bazı özellikler, üst öğenin işleme özelliklerini diğer şekillerde etkiler. Örneğin, özelliğinde MinOrphanLines yapılan değişiklikler bir akış belgesinin genel işlemesini değiştirebilir. Kendi AffectsParentArrangeAffectsParentMeasure özelliklerinizin üst eylemlerini sinyal olarak kullanmak için veya kullanın.

  • Varsayılan olarak, bağımlılık özellikleri veri bağlamayı destekler. Ancak, bunun için gerçekçi bir senaryo yoksa veya büyük nesnelerde olduğu gibi veri bağlama performansının sorunlu olduğu durumlarda veri bağlamayı IsDataBindingAllowed devre dışı bırakmak için kullanabilirsiniz.

  • Bağımlılık özellikleri için varsayılan veri bağlama modu olsa da, belirli bir bağlamanın bağlama modunu olarak TwoWay değiştirebilirsiniz. Daha fazla bilgi için bkz. Bağlama yönü. Bağımlılık özelliği yazarı olarak, varsayılan modu iki yollu bağlamayı bile seçebilirsiniz. İki yollu veri bağlama kullanan mevcut bağımlılık özelliğine örnek olarak, diğer özellikleri ve yöntem çağrılarını temel alan MenuItem.IsSubmenuOpen bir durumu vardır. için senaryo, ayar mantığının ve birleştirmenin IsSubmenuOpen varsayılan tema MenuItem stiliyle etkileşim kurmasıdır. TextBox.Text , varsayılan olarak iki yollu bağlama kullanan başka bir WPF bağımlılık özelliğidir.

  • bayrağını ayarerek bağımlılık özelliğiniz için özellik devralmayı Inherits etkinleştirebilirsiniz. Özellik devralma, üst ve alt öğelerin ortak bir özelliği olduğu ve alt öğenin ortak özelliğin üst değerini devralması mantıklı olduğu senaryolar için yararlıdır. Devralınabilir bir özellik örneği, veri sunumu için ana ayrıntı senaryosunu DataContextDataContext destekleyen özelliğidir. Özellik değeri devralma, sayfada veya uygulama kökünde bir veri bağlamı belirtmenize olanak sağlar ve bu da alt öğe bağlamaları için belirtmek zorunda kalmadan bunu kaydeder. Devralınan özellik değeri varsayılan değeri geçersiz kılsa da, özellik değerleri herhangi bir alt öğede yerel olarak ayarılabilir. Özellik değeri devralma özelliğini performans maliyetine sahip olduğu için kullanın. Daha fazla bilgi için bkz. Özellik değeri devralma.

  • Bağımlılık Journal özelliğinizin gezinti günlük hizmetleri tarafından algılandığında veya kullanılmalı olduğunu belirtmek için bayrağını ayarlayın. Örneğin özelliği, SelectedIndex uygulamaların seçilen öğelerin günlük geçmişini Journal tutmalarını önerecek şekilde bayrağını ayarlar.

Salt okunur bağımlılık özellikleri

Salt okunur bir bağımlılık özelliği tanımlayabilirsiniz. Tipik bir senaryo, iç durumu depolar bir bağımlılık özelliğidir. Örneğin, IsMouseOver durumu yalnızca fare girişi tarafından belirlenecek olduğundan salt okunur olur. Daha fazla bilgi için bkz. Salt okunur bağımlılık özellikleri.

Koleksiyon türü bağımlılık özellikleri

Koleksiyon türü bağımlılık özellikleri, başvuru türleri için varsayılan değer ayarlama ve koleksiyon öğeleri için veri bağlama desteği gibi ek uygulama sorunlarına sahiptir. Daha fazla bilgi için bkz. Koleksiyon türü bağımlılık özellikleri.

Bağımlılık özelliği güvenliği

Genellikle, bağımlılık özelliklerini genel özellikler olarak, tanımlayıcı alanlarını DependencyProperty da alan olarak public static readonly bildirebilirsiniz. gibi daha kısıtlayıcı bir erişim düzeyi belirtirsiniz, bağımlılık özelliğine, özellik sistemi API'leriyle birlikte tanımlayıcısı protected üzerinden erişilebilir. Korumalı tanımlayıcı alanı bile WPF meta veri raporlaması veya gibi değer belirleme API'leri aracılığıyla erişilebilir LocalValueEnumerator olabilir. Daha fazla bilgi için bkz. Bağımlılık özelliği güvenliği.

Salt okunur bağımlılık özellikleri için, değerinden döndürülen değerdir ve genellikle RegisterReadOnlyDependencyPropertyKey sınıfınıza DependencyPropertyKey üye public olmayacaktır. WPF özellik sistemi kodunuzun dışında yaymaysa da salt okunur bağımlılık özelliği, okuma-yazma bağımlılık özelliğinden DependencyPropertyKeyset daha iyi güvenlik sağlar.

Bağımlılık özellikleri ve sınıf oluşturucuları

Yönetilen kod programlamada genellikle kod analizi araçları tarafından zorlanan ve sınıf oluşturucuların sanal yöntemleri çağırmaması gereken genel bir ilke vardır. Bunun nedeni, temel oluşturucuların türetilmiş bir sınıf oluşturucusu başlatma sırasında çağrılmalarının ve bir temel oluşturucu tarafından çağrılan sanal yöntemin türetilmiş sınıfın tam olarak başlatılamadan önce çalışmasıdır. zaten 'den türetmiş olan bir sınıftan türeyen, özellik sisteminin kendisi sanal DependencyObject yöntemleri dahili olarak çağıran ve ortaya çıkarır. Bu sanal yöntemler WPF özellik sistemi hizmetlerinin bir parçasıdır. Yöntemleri geçersiz kılma, türetilmiş sınıfların değer belirlemeye katılmalarını sağlar. Çalışma zamanı başlatmayla ilgili olası sorunları önlemek için, belirli bir oluşturucu desenini izlemedikçe, sınıfların oluşturucuları içinde bağımlılık özelliği değerlerini ayarlamamanız gerekir. Daha fazla bilgi için bkz. DependencyObjects Kasa oluşturucu desenlerini oluşturma.

Ayrıca bkz.