Bağımlılık Özelliği Geri Aramaları ve Doğrulama

Bu konuda, doğrulama belirleme, özelliğin etkin değeri her değiştirildiğinde çağrılan geri çağırmalar ve değer belirleme üzerindeki olası dış etkileri geçersiz kılma gibi özellikle ilgili özellikler için alternatif özel uygulamalar kullanılarak bağımlılık özelliklerinin nasıl oluşturulacağı açıklanmaktadır. Bu konu başlığı altında, bu teknikleri kullanarak varsayılan özellik sistemi davranışlarını genişletmenin uygun olduğu senaryolar da ele alınmaktadır.

Ön koşullar

Bu konu başlığında, bağımlılık özelliği uygulamayla ilgili temel senaryoları ve meta verilerin özel bağımlılık özelliğine nasıl uygulandığını anladığınız varsayılır. Bağlam için bkz . Özel Bağımlılık Özellikleri ve Bağımlılık Özelliği Meta Verileri .

Doğrulama Geri Çağırmaları

Doğrulama geri çağırmaları, ilk kaydettiğinizde bağımlılık özelliğine atanabilir. Doğrulama geri çağırma özelliği meta verilerinin bir parçası değildir; yönteminin Register doğrudan bir girişidir. Bu nedenle, bir bağımlılık özelliği için doğrulama geri çağırması oluşturulduktan sonra, yeni bir uygulama tarafından geçersiz kılınamaz.

public static readonly DependencyProperty CurrentReadingProperty = DependencyProperty.Register(
    "CurrentReading",
    typeof(double),
    typeof(Gauge),
    new FrameworkPropertyMetadata(
        Double.NaN,
        FrameworkPropertyMetadataOptions.AffectsMeasure,
        new PropertyChangedCallback(OnCurrentReadingChanged),
        new CoerceValueCallback(CoerceCurrentReading)
    ),
    new ValidateValueCallback(IsValidReading)
);
public double CurrentReading
{
  get { return (double)GetValue(CurrentReadingProperty); }
  set { SetValue(CurrentReadingProperty, value); }
}
Public Shared ReadOnly CurrentReadingProperty As DependencyProperty =
    DependencyProperty.Register("CurrentReading",
        GetType(Double), GetType(Gauge),
        New FrameworkPropertyMetadata(Double.NaN,
            FrameworkPropertyMetadataOptions.AffectsMeasure,
            New PropertyChangedCallback(AddressOf OnCurrentReadingChanged),
            New CoerceValueCallback(AddressOf CoerceCurrentReading)),
        New ValidateValueCallback(AddressOf IsValidReading))

Public Property CurrentReading() As Double
    Get
        Return CDbl(GetValue(CurrentReadingProperty))
    End Get
    Set(ByVal value As Double)
        SetValue(CurrentReadingProperty, value)
    End Set
End Property

Geri çağırmalar, nesne değeri sağlanacak şekilde uygulanır. Sağlanan değer özelliği için geçerliyse döndürür true ; aksi takdirde döndürür false. Özelliğin, özellik sistemiyle kaydedilen tür başına doğru türde olduğu varsayılır, bu nedenle geri çağırmalar içindeki tür denetimi normalde yapılmaz. Geri çağırmalar, özellik sistemi tarafından çeşitli farklı işlemlerde kullanılır. Bu, varsayılan değere göre ilk tür başlatmayı, çağrılarak SetValueprogramlı değişikliği veya sağlanan yeni varsayılan değerle meta verileri geçersiz kılma girişimlerini içerir. Doğrulama geri çağırması bu işlemlerden herhangi biri tarafından çağrılır ve döndürürse false, bir özel durum oluşturulur. Uygulama yazarları bu özel durumları işlemeye hazır olmalıdır. Doğrulama geri çağırmalarının yaygın bir kullanımı, numaralandırma değerlerini doğrulamak veya özellik sıfır veya daha büyük olması gereken ölçümleri ayarlarken tamsayı veya çift değerlerini kısıtlamaktır.

Doğrulama geri çağırmaları, örnek doğrulayıcıları değil, özellikle sınıf doğrulayıcıları olarak tasarlanmıştır. Geri çağırma parametreleri, doğrulanması gereken özelliklerin ayarlandığı belirli DependencyObject bir şeyi iletmez. Bu nedenle doğrulama geri çağırmaları, bir özelliğin örneğe özgü değerinin diğer özelliklerin örneğe özgü değerleri veya çalışma zamanı durumu gibi faktörlere bağımlı olduğu bir özellik değerini etkileyebilecek olası "bağımlılıkları" zorlamak için kullanışlı değildir.

Aşağıda, çok basit bir doğrulama geri çağırma senaryosu için örnek kod verilmiştir: ilkel olarak Double yazılan bir özelliğin veya NegativeInfinityolmadığını PositiveInfinity doğrulama.

public static bool IsValidReading(object value)
{
    Double v = (Double)value;
    return (!v.Equals(Double.NegativeInfinity) && !v.Equals(Double.PositiveInfinity));
}
Public Shared Function IsValidReading(ByVal value As Object) As Boolean
    Dim v As Double = CType(value, Double)
    Return ((Not v.Equals(Double.NegativeInfinity)) AndAlso
            (Not v.Equals(Double.PositiveInfinity)))
End Function

Zorlama Değeri Geri Çağırmaları ve Özellik Değişen Olayları

Zorlama değeri geri çağırmaları, bir bağımlılık özelliğinin değeri her değiştiğinde özellik sistemi tarafından çağrılan uygulamalar gibi PropertyChangedCallback özellikler için belirli DependencyObject bir örneği geçirir. Bu iki geri çağırmayı birlikte kullanarak, bir özellikteki değişikliklerin başka bir özelliği zorlamaya veya yeniden değerlendirmeye zorladığı öğelerde bir dizi özellik oluşturabilirsiniz.

Bağımlılık özelliklerinin bağlantısını kullanmak için tipik bir senaryo, öğenin en düşük ve en yüksek değer için her biri bir özelliğin ve gerçek veya geçerli değer için üçüncü bir özelliğin bulunduğu kullanıcı arabirimi temelli bir özelliğiniz olmasıdır. Burada maksimum değer, geçerli değerin yeni maksimum değeri aşacak şekilde ayarlandıysa, geçerli değeri yeni maksimumdan büyük olmayacak şekilde zorlamak ve minimum ile geçerli arasında benzer bir ilişki oluşturmak isteyebilirsiniz.

Aşağıda, bu ilişkiyi gösteren üç bağımlılık özelliğinden yalnızca biri için çok kısa bir örnek kod verilmiştir. Örnek, ilgili *Okuma özelliklerinin Min/Max/Current kümesinin özelliğinin nasıl CurrentReading kaydedildiği gösterir. Önceki bölümde gösterildiği gibi doğrulamayı kullanır.

public static readonly DependencyProperty CurrentReadingProperty = DependencyProperty.Register(
    "CurrentReading",
    typeof(double),
    typeof(Gauge),
    new FrameworkPropertyMetadata(
        Double.NaN,
        FrameworkPropertyMetadataOptions.AffectsMeasure,
        new PropertyChangedCallback(OnCurrentReadingChanged),
        new CoerceValueCallback(CoerceCurrentReading)
    ),
    new ValidateValueCallback(IsValidReading)
);
public double CurrentReading
{
  get { return (double)GetValue(CurrentReadingProperty); }
  set { SetValue(CurrentReadingProperty, value); }
}
Public Shared ReadOnly CurrentReadingProperty As DependencyProperty =
    DependencyProperty.Register("CurrentReading",
        GetType(Double), GetType(Gauge),
        New FrameworkPropertyMetadata(Double.NaN,
            FrameworkPropertyMetadataOptions.AffectsMeasure,
            New PropertyChangedCallback(AddressOf OnCurrentReadingChanged),
            New CoerceValueCallback(AddressOf CoerceCurrentReading)),
        New ValidateValueCallback(AddressOf IsValidReading))

Public Property CurrentReading() As Double
    Get
        Return CDbl(GetValue(CurrentReadingProperty))
    End Get
    Set(ByVal value As Double)
        SetValue(CurrentReadingProperty, value)
    End Set
End Property

Current için değiştirilen geri çağırma özelliği, değişikliği diğer bağımlı özelliklere iletmek için kullanılır ve bu diğer özellikler için kaydedilen zorlama değeri geri çağırmaları açıkça çağrılır:

private static void OnCurrentReadingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
  d.CoerceValue(MinReadingProperty);
  d.CoerceValue(MaxReadingProperty);
}
Private Shared Sub OnCurrentReadingChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
    d.CoerceValue(MinReadingProperty)
    d.CoerceValue(MaxReadingProperty)
End Sub

Zorlama değeri geri çağırması, geçerli özelliğin bağımlı olma olasılığı olan özelliklerin değerlerini denetler ve gerekirse geçerli değeri zorunlu hale getirir:

private static object CoerceCurrentReading(DependencyObject d, object value)
{
  Gauge g = (Gauge)d;
  double current = (double)value;
  if (current < g.MinReading) current = g.MinReading;
  if (current > g.MaxReading) current = g.MaxReading;
  return current;
}
Private Shared Function CoerceCurrentReading(ByVal d As DependencyObject, ByVal value As Object) As Object
    Dim g As Gauge = CType(d, Gauge)
    Dim current As Double = CDbl(value)
    If current < g.MinReading Then
        current = g.MinReading
    End If
    If current > g.MaxReading Then
        current = g.MaxReading
    End If
    Return current
End Function

Dekont

Özelliklerin varsayılan değerleri zorunlu değildir. Bir özellik değeri hala ilk varsayılan değerine sahipse veya ile ClearValuediğer değerleri temizleyerek varsayılan değere eşit bir özellik değeri oluşabilir.

Zorlama değeri ve özellik değişikliği geri çağırmaları özellik meta verilerinin bir parçasıdır. Bu nedenle, bağımlılık özelliğinin sahibi olan türden türetdiğiniz bir tür üzerinde mevcut olduğu için belirli bir bağımlılık özelliği için geri çağırmaları değiştirebilirsiniz. Bu özelliğin meta verilerini türünüzde geçersiz kılabilirsiniz.

Gelişmiş Zorlama ve Geri Çağırma Senaryoları

Kısıtlamalar ve İstenen Değerler

Geri CoerceValueCallback çağırmalar, bir değeri bildirdiğiniz mantığa göre zorlamak için özellik sistemi tarafından kullanılır, ancak yerel olarak ayarlanmış bir özelliğin zorlamalı değeri dahili olarak "istenen değeri" korumaya devam eder. Kısıtlamalar, uygulama ömrü boyunca dinamik olarak değişebilecek diğer özellik değerlerini temel alırsa, zorlama kısıtlamaları da dinamik olarak değiştirilir ve kısıtlanmış özellik, yeni kısıtlamalar göz önüne alındığında istenen değere mümkün olduğunca yakın olacak şekilde değerini değiştirebilir. Tüm kısıtlamalar kaldırılırsa değer istenen değer olur. Döngüsel bir şekilde birbirine bağımlı birden çok özelliğiniz varsa, bazı oldukça karmaşık bağımlılık senaryoları sunabilirsiniz. Örneğin, En Küçük/En Yüksek/Geçerli senaryosunda, kullanıcı ayarlanabilir en düşük ve en fazla seçeneklerini seçebilirsiniz. Bu durumda, Maksimum değerinin her zaman Minimum'dan büyük ve tam tersi olduğunu zorlamanız gerekebilir. Ancak bu zorlama etkinse ve Maksimum zorlama Minimum ise, Her ikisine de bağımlı olduğundan ve değerler arasındaki aralıkla kısıtlandığından (sıfır) Current değerini ayarsız durumda bırakır. Ardından, En Büyük veya En Düşük ayarlanırsa, geçerli değerin istenen değeri hala depolandığından ve kısıtlamalar gevşetildikçe istenen değere ulaşmaya çalıştığından, Geçerli değerlerden birini "takip ediyor" gibi görünür.

Karmaşık bağımlılıklarla ilgili teknik olarak yanlış bir şey yoktur, ancak çok fazla sayıda yeniden değerlendirmeye ihtiyaç duyduklarında hafif bir performans zararları olabilir ve kullanıcı arabirimini doğrudan etkileyen kullanıcılar için kafa karıştırıcı olabilir. Özellik değişikliğine ve zorlayıcı değer geri çağırmalarına dikkat edin ve denenen zorlamanın mümkün olduğunca belirsiz olarak ele alınaabildiğinden ve "aşırı sınırlanmadığından" emin olun.

Değer Değişikliklerini İptal Etmek için CoerceValue Kullanma

Özellik sistemi, değeri UnsetValue özel durum olarak döndüren herhangi CoerceValueCallback birini değerlendirir. Bu özel durum, çağrılmayla sonuçlanan özellik değişikliğinin CoerceValueCallback özellik sistemi tarafından reddedilmesi ve özellik sisteminin bunun yerine özelliğin önceki değerini raporlaması gerektiği anlamına gelir. Bu mekanizma, zaman uyumsuz olarak başlatılan bir özellikteki değişikliklerin geçerli nesne durumu için hala geçerli olup olmadığını denetlemek ve geçerli değilse değişiklikleri engellemek için yararlı olabilir. Başka bir olası senaryo, bildirilen değerden hangi özellik değeri belirleme bileşeninin sorumlu olduğuna bağlı olarak bir değeri seçmeli olarak gizleyebilmenizdir. Bunu yapmak için, geri çağırmada geçirilen öğesini DependencyProperty ve özellik tanımlayıcısını için GetValueSourcegiriş olarak kullanabilir ve ardından işlemini gerçekleştirebilirsiniz ValueSource.

Ayrıca bkz.