Ö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, Widthve Text WPF sınıflarındaki mevcut bağımlılık özelliklerine örnektir. Bu makalede özel bağımlılık özelliklerinin nasıl uygulandığı açıklanır ve performans, kullanılabilirlik ve çok yönlülüğü geliştirmeye yönelik seçenekler sunulur.

Önemli

.NET 7 ve .NET 6 için Masaüstü Kılavuzu belgeleri yapım aşamasındadır.

Ön koşullar

Makalede bağımlılık özellikleri hakkında temel bilgiler edindiğiniz ve Bağımlılık özelliklerine genel bakış makalesini okuduğunuz varsayılır. Bu makaledeki örnekleri takip etmek için Genişletilebilir Uygulama biçimlendirme dili (XAML) hakkında bilgi sahibi olmanız ve WPF uygulamalarının nasıl yazabileceğinizi bilmeniz yardımcı olur.

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

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

Bağımlılık özelliği tanımlayıcısı, bir özelliği özel alanla yedeklemenin standart deseni yerine özellik değerlerini almak veya ayarlamak için bir yedekleme alanı olarak kullanılır. Özellik sistemi yalnızca tanımlayıcıyı kullanmaz, XAML işlemcileri bunu kullanabilir ve kodunuz (ve muhtemelen dış kod) bağımlılık özelliklerine tanımlayıcıları aracılığıyla erişebilir.

Bağımlılık özellikleri yalnızca türlerden DependencyObject türetilen sınıflara uygulanabilir. WPF sınıflarının çoğu, WPF sınıf hiyerarşisinin köküne yakın olduğundan DependencyObject bağımlılık ö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 özellikler olmayan WPF bağımlılık özellikleri, ve set erişimcileri get uygulayan bir CLR sarmalayıcısı tarafından kullanıma sunulur. Özellik sarmalayıcı kullanarak, bağımlılık özelliklerinin tüketicileri diğer CLR özellikleri gibi bağımlılık özelliği değerlerini alabilir veya ayarlayabilir. get ve set erişimcileri, bağımlılık özelliği tanımlayıcısını parametre olarak geçirerek ve DependencyObject.SetValue çağrıları aracılığıyla DependencyObject.GetValue temel alınan özellik sistemiyle etkileşim kurar. Bağımlılık özelliklerinin tüketicileri genellikle doğrudan veya SetValue çağırmazGetValue, ancak özel bağımlılık özelliği uyguluyorsanız sarmalayıcıda bu yöntemleri kullanırsınız.

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

öğesinden DependencyObjecttüretilen bir sınıfa bir özellik uyguladığınızda, özelliğinizi bir tanımlayıcıyla destekleyerek bunu bir DependencyProperty bağımlılık özelliği haline getirirsiniz. Bağımlılık özelliği oluşturmanın yararlı olup olmadığı senaryonuza bağlıdır. Özelliğinizi özel bir alanla yedeklemek bazı senaryolar için yeterli olsa da, özelliğinizin aşağıdaki WPF özelliklerinden birini veya daha fazlasını desteklemesini istiyorsanız bir bağımlılık özelliği uygulamayı göz önünde bulundurun:

  • Bir stil içinde ayarlanabilen ö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 ayarlanabilen özellikler. Daha fazla bilgi için bkz . XAML kaynakları.

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

  • Düşünülebilir özellikler. Daha fazla bilgi için bkz. Animasyona genel bakış.

  • Bir özellik değeri değiştiğinde WPF özellik sistemi tarafından bildirim. Değişiklikler, özellik sistemi, ortam, kullanıcı veya stillere göre eylemlerden kaynaklanıyor olabilir. Özelliğiniz özellik meta verilerinde özellik sistemi özellik değerinizin değiştiğini her belirlediği zaman çağrılacak bir geri çağırma yöntemi belirtebilir. İ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ğrulama.

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

    • Değiştirilen bağımlılık özelliği değerinin düzen sisteminin bir öğe için görselleri yeniden derlemesine neden olup olmayacağını belirtin.

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

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

Bazı senaryolarda, var olan bir bağımlılık özelliğinin meta verilerini geçersiz kılma, yeni bir bağımlılık özelliği uygulamaktan daha iyi bir seçenektir. Meta veri geçersiz kılmanın pratik olup olmadığı senaryonuza ve bu senaryonun mevcut WPF bağımlılık özellikleri ve sınıflarının uygulanmasına ne kadar yakın olduğuna bağlıdır. Meta verileri mevcut bağımlılık özelliklerinde 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ında birleştirilebilir ve uygulanabilir.

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

  2. Özellik adını, sahip türünü, özellik değer türünü ve isteğe bağlı olarak özellik meta verilerini belirterek bağımlılık özelliğini özellik sistemine kaydedin.

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

  4. Bağımlılık özellik adıyla aynı ada sahip bir CLR sarmalayıcı özelliği tanımlayın. CLR sarmalayıcısında, sarmalayıcıyı destekleyen bağımlılık özelliğiyle bağlanan ve set erişimcilerini uygulayınget.

Özelliği kaydetme

Özelliğinizin bir bağımlılık özelliği olması için özelliği özellik sistemine kaydetmeniz gerekir. Özelliğinizi kaydetmek için, sınıfınızın gövdesinin içinden ancak üye tanımlarının dışında yöntemini çağırın Register . yöntemi, Register özellik sistemi API'sini çağırırken kullanacağınız benzersiz bir bağımlılık özelliği tanımlayıcısı döndürür. Çağrının Register üye tanımlarının dışında yapılmasının nedeni, dönüş değerini türünde DependencyPropertybir public static readonly alana atamanızdır. Sınıfınızda oluşturacağınız 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 Register bağımlılık özelliğini AquariumGraphicadlandırmaktadı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))
    );
' 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)))

Dekont

Sınıf gövdesinde bağımlılık özelliğini tanımlamak tipik bir uygulamadır, ancak sınıf statik oluşturucusunda 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ırma

Bağımlılık özellikleri için oluşturulan adlandırma kuralı, özellik sisteminin normal davranışı için zorunludur. Oluşturduğunuz tanımlayıcı alanının adı, özelliğin sonekiyle Propertybirlikte kayıtlı adı olmalıdır.

Bağımlılık özellik adı, kayıt sınıfında benzersiz olmalıdır. Bir temel tür aracılığıyla devralınan bağımlılık özellikleri zaten kaydedilmiş ve türetilmiş bir tür tarafından kaydedilemez. Ancak, sınıfınızı bağımlılık özelliğinin sahibi olarak ekleyerek sınıfınızın devralmadığı bir tür bile dahil olmak üzere 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 çağrının Register ilk parametresiyle aynı olmalıdır. Sarmalayıcı uygulamanız erişimciyi get ve erişimciyi set (okuma-yazma özellikleri için) çağırır GetValueSetValue. Aşağıdaki örnekte, kayıt çağrısı ve tanımlayıcı alanı bildiriminin ardından bir sarmalayıcı gösterilmektedir. 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 SetValue kodu içermelidirGetValue. Bunun ardındaki nedenler için bkz . Özel bağımlılık özelliklerinin etkileri.

Özelliğiniz yerleşik adlandırma kurallarına uymuyorsa şu sorunlarla karşılaşabilirsiniz:

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

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

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

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

Bağımlılık özelliğini kaydettiğinizde, özellik sistemi özellik özelliklerini depolamak için bir meta veri nesnesi oluşturur. yönteminin Register aşırı yüklemeleri, kayıt sırasında özellik meta verilerini belirtmenize olanak tanır, örneğin Register(String, Type, Type, PropertyMetadata). Özellik meta verilerinin yaygın bir kullanımı, bağımlılık özelliği kullanan yeni örnekler için özel bir varsayılan değer uygulamaktır. Özellik meta verilerini sağlamazsanız, özellik sistemi bağımlılık özelliği özelliklerinin çoğuna varsayılan değerler atar.

öğesinden FrameworkElementtüretilmiş bir sınıfta bağımlılık özelliği oluşturuyorsanız, temel sınıfı FrameworkPropertyMetadata yerine daha özelleştirilmiş meta veri sınıfını PropertyMetadatakullanabilirsiniz. Çeşitli FrameworkPropertyMetadata oluşturucu imzaları, meta veri özelliklerinin farklı birleşimlerini belirtmenize olanak tanır. Yalnızca bir varsayılan değer belirtmek istiyorsanız, kullanın FrameworkPropertyMetadata(Object) ve varsayılan değeri parametresine Object geçirin. Değer türünün çağrıda belirtilen değer türüyle propertyType eşleştiğinden Register emin olun.

Bazı FrameworkPropertyMetadata aşırı yüklemeler, özelliğiniz için meta veri seçeneği bayrakları belirtmenize olanak tanır. Ö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 aşağıdakileri göz önünde bulundurun:

  • Özellik değeriniz (veya bu değere yapılan değişiklikler) düzen sisteminin bir UI öğ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 kullanıcı arabirimi işlemesinde, özellikle de üst öğesindeki bir nesnenin kapladığı alanda değişiklik gerektirdiğini gösterir. Örneğin, bir Width özellik için bu meta veri bayrağını ayarlayın.

    • AffectsArrange, özellik değerindeki bir değişikliğin kullanıcı arabirimi işlemede, özellikle de bir nesnenin üst öğesindeki konumuyla ilgili bir değişiklik gerektirdiğini gösterir. Genellikle nesnenin boyutu da değişmez. Örneğin, bir Alignment özellik için bu meta veri bayrağını ayarlayın.

    • AffectsRender, düzeni ve ölçüyü etkilemeyen ancak yine de başka bir işleme gerektiren bir değişiklik olduğunu gösterir. Örneğin, bir özellik veya öğenin rengini etkileyen başka bir Background özellik için bu bayrağı 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 OnPropertyChanged değer değişikliği bildirdiğinde ve AffectsArrange meta verilerde ayarlandığında çağırmak InvalidateArrange için bir geri çağırma kullanabilirsiniz.

  • Bazı özellikler üst öğelerinin işleme özelliklerini başka şekillerde etkiler. Örneğin, özelliğindeki MinOrphanLines değişiklikler bir akış belgesinin genel olarak işlenmesini değiştirebilir. Kendi özelliklerinizde üst eylemlerin sinyalini vermek için veya AffectsParentMeasure kullanınAffectsParentArrange.

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

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

  • Bayrağını ayarlayarak Inherits bağımlılık özelliğiniz için özellik devralmayı etkinleştirebilirsiniz. Özellik devralma, üst ve alt öğelerin ortak bir özelliğe sahip olduğu senaryolar için kullanışlıdır ve alt öğenin ortak özelliğin üst değerini devralmaları mantıklıdır. Devralınabilir özellik örneği, veri sunumu için ana ayrıntı senaryoyu kullanan bağlama işlemlerini destekleyen özelliğidirDataContext. Özellik değeri devralma, sayfa veya uygulama kökünde bir veri bağlamı belirtmenize olanak tanır ve bu da bunu alt öğe bağlamaları için belirtmeye gerek kalmadan kaydeder. Devralınan bir özellik değeri varsayılan değeri geçersiz kılsa da, özellik değerleri herhangi bir alt öğede yerel olarak ayarlanabilir. Bir performans maliyeti olduğundan özellik değeri devralmayı dikkate almadan kullanın. Daha fazla bilgi için bkz . Özellik değeri devralma.

  • Journal Bağımlılık özelliğinizin algılanması veya gezinti günlüğü hizmetleri tarafından kullanılması gerektiğini belirtmek için bayrağını ayarlayın. Örneğin özelliği, SelectedIndex uygulamaların seçilen öğelerin günlük geçmişini tutmasını önermek için bayrağını ayarlar Journal .

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

Salt okunur bir bağımlılık özelliği tanımlayabilirsiniz. Tipik bir senaryo, iç durumu depolayan bir bağımlılık özelliğidir. Örneğin, IsMouseOver salt okunurdur çünkü durumu yalnızca fare girişi tarafından belirlenmelidir. 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 özelliklerinin, başvuru türleri için varsayılan bir değer ayarlama ve koleksiyon öğeleri için veri bağlama desteği gibi dikkate alınması gereken ek uygulama sorunları vardır. 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ı da DependencyProperty alan olarak public static readonly bildirirsiniz. gibi protecteddaha kısıtlayıcı bir erişim düzeyi belirtirseniz, bağımlılık özelliğine yine de tanımlayıcısı üzerinden özellik sistemi API'leri ile birlikte erişilebilir. Korumalı bir tanımlayıcı alanına bile WPF meta veri raporlaması veya değer belirleme API'leri aracılığıyla (gibi LocalValueEnumerator) erişilebilir. Daha fazla bilgi için bkz . Bağımlılık özelliği güvenliği.

Salt okunur bağımlılık özellikleri için, öğesinden RegisterReadOnly döndürülen değerdir DependencyPropertyKeyve genellikle sınıfınızın üyesi public olmazsınızDependencyPropertyKey. WPF özellik sistemi kodunuzun DependencyPropertyKey dışına yayılmadığından, salt okunur bağımlılık özelliği, okuma-yazma bağımlılık özelliğinden daha iyi set bir güvenliğe sahiptir.

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

Yönetilen kod programlamada genellikle kod çözümleme araçları tarafından zorlanan, sınıf oluşturucularını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şlatılırken çağrılabilmesi ve temel oluşturucu tarafından çağrılan bir sanal yöntemin türetilmiş sınıfın tam olarak başlatılmasından önce çalıştırılabilmesidir. zaten öğesinden türetilen bir sınıftan türetdiğinizde DependencyObject, özellik sisteminin kendisi sanal yöntemleri dahili olarak çağırır ve kullanıma sunar. 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ılmasını sağlar. Çalışma zamanı başlatmayla ilgili olası sorunları önlemek için, belirli bir oluşturucu desenini izlemediğiniz sürece sınıfların oluşturucuları içinde bağımlılık özelliği değerlerini ayarlamamalısınız. Daha fazla bilgi için bkz. DependencyObjects için Kasa oluşturucu desenleri.

Ayrıca bkz.