Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Artikel ini menjelaskan cara menentukan properti dependensi dan menerapkan panggilan balik properti dependensi. Panggilan balik mendukung validasi nilai, koersi nilai, dan logika lain yang diperlukan saat nilai properti berubah.
Prasyarat
Artikel ini mengasumsikan pengetahuan dasar tentang properti dependensi, dan Anda telah membaca gambaran umum properti dependensi . Untuk mengikuti contoh dalam artikel ini, ini membantu jika Anda terbiasa dengan Extensible Application Markup Language (XAML) dan tahu cara menulis aplikasi WPF.
Memvalidasi nilai dengan panggilan balik
Panggilan balik nilai validasi menyediakan cara bagi Anda untuk memeriksa apakah nilai properti dependensi baru valid sebelum diterapkan oleh sistem properti. Panggilan balik ini menimbulkan pengecualian jika nilai tidak memenuhi kriteria validasi.
Panggilan balik nilai validasi hanya dapat ditetapkan ke properti dependensi sekali, selama pendaftaran properti. Saat mendaftarkan properti dependensi, Anda memiliki opsi untuk memberikan ValidateValueCallback referensi ke metode Register(String, Type, Type, PropertyMetadata, ValidateValueCallback). Fungsi panggilan balik validasi nilai bukan bagian dari metadata properti, dan tidak dapat diubah.
Nilai efekti dari sebuah properti dependensi adalah nilainya setelah diterapkan. Nilai efektif ditentukan melalui nilai properti yang diutamakan ketika ada beberapa input berbasis properti. Jika panggilan balik validasi-nilai didaftarkan untuk properti dependensi, sistem properti akan memanggil panggilan balik validasi-nilai ketika nilai berubah, memberikan nilai baru sebagai objek. Dalam panggilan balik, Anda dapat melemparkan kembali objek nilai ke jenis yang terdaftar dengan sistem properti, lalu menjalankan logika validasi Anda di atasnya. Panggilan balik mengembalikan true jika nilai valid untuk properti , jika tidak false.
Jika panggilan balik nilai validasi mengembalikan false, pengecualian dinaikkan dan nilai baru tidak diterapkan. Penulis aplikasi harus siap untuk menangani pengecualian ini. Penggunaan umum panggilan balik nilai validasi adalah memvalidasi nilai enumerasi, atau membatasi nilai numerik saat mewakili pengukuran yang memiliki batasan. Panggilan balik validasi nilai dipanggil oleh sistem properti dalam berbagai skenario, termasuk:
- Inisialisasi objek, yang menerapkan nilai default pada waktu pembuatan.
- Panggilan terprogram ke SetValue.
- Pengaturan ulang metadata yang menetapkan nilai default baru.
Panggilan balik nilai validasi tidak memiliki parameter yang menentukan instans DependencyObject tempat nilai baru ditetapkan. Semua instans DependencyObject berbagi fungsi pengembalian validasi-nilai yang sama, sehingga tidak dapat digunakan untuk memvalidasi skenario spesifik instans. Untuk informasi selengkapnya, lihat ValidateValueCallback .
Contoh berikut menunjukkan cara mencegah properti, ditik sebagai Double, diatur ke PositiveInfinity atau NegativeInfinity.
public class Gauge1 : Control
{
public Gauge1() : base() { }
// Register a dependency property with the specified property name,
// property type, owner type, property metadata, and callbacks.
public static readonly DependencyProperty CurrentReadingProperty =
DependencyProperty.Register(
name: "CurrentReading",
propertyType: typeof(double),
ownerType: typeof(Gauge1),
typeMetadata: new FrameworkPropertyMetadata(
defaultValue: double.NaN,
flags: FrameworkPropertyMetadataOptions.AffectsMeasure),
validateValueCallback: new ValidateValueCallback(IsValidReading));
// CLR wrapper with get/set accessors.
public double CurrentReading
{
get => (double)GetValue(CurrentReadingProperty);
set => SetValue(CurrentReadingProperty, value);
}
// Validate-value callback.
public static bool IsValidReading(object value)
{
double val = (double)value;
return !val.Equals(double.NegativeInfinity) &&
!val.Equals(double.PositiveInfinity);
}
}
Public Class Gauge1
Inherits Control
Public Sub New()
MyBase.New()
End Sub
Public Shared ReadOnly CurrentReadingProperty As DependencyProperty =
DependencyProperty.Register(
name:="CurrentReading",
propertyType:=GetType(Double),
ownerType:=GetType(Gauge1),
typeMetadata:=New FrameworkPropertyMetadata(
defaultValue:=Double.NaN,
flags:=FrameworkPropertyMetadataOptions.AffectsMeasure),
validateValueCallback:=New ValidateValueCallback(AddressOf IsValidReading))
Public Property CurrentReading As Double
Get
Return GetValue(CurrentReadingProperty)
End Get
Set(value As Double)
SetValue(CurrentReadingProperty, value)
End Set
End Property
Public Shared Function IsValidReading(value As Object) As Boolean
Dim val As Double = value
Return Not val.Equals(Double.NegativeInfinity) AndAlso
Not val.Equals(Double.PositiveInfinity)
End Function
End Class
public static void TestValidationBehavior()
{
Gauge1 gauge = new();
Debug.WriteLine($"Test value validation scenario:");
// Set allowed value.
gauge.CurrentReading = 5;
Debug.WriteLine($"Current reading: {gauge.CurrentReading}");
try
{
// Set disallowed value.
gauge.CurrentReading = double.PositiveInfinity;
}
catch (ArgumentException e)
{
Debug.WriteLine($"Exception thrown by ValidateValueCallback: {e.Message}");
}
Debug.WriteLine($"Current reading: {gauge.CurrentReading}");
// Current reading: 5
// Exception thrown by ValidateValueCallback: '∞' is not a valid value for property 'CurrentReading'.
// Current reading: 5
}
Public Shared Sub TestValidationBehavior()
Dim gauge As New Gauge1()
Debug.WriteLine($"Test value validation scenario:")
' Set allowed value.
gauge.CurrentReading = 5
Debug.WriteLine($"Current reading: {gauge.CurrentReading}")
Try
' Set disallowed value.
gauge.CurrentReading = Double.PositiveInfinity
Catch e As ArgumentException
Debug.WriteLine($"Exception thrown by ValidateValueCallback: {e.Message}")
End Try
Debug.WriteLine($"Current reading: {gauge.CurrentReading}")
' Current reading: 5
' Exception thrown by ValidateValueCallback: '∞' is not a valid value for property 'CurrentReading'.
' Current reading 5
End Sub
Panggilan balik ketika properti berubah
Panggilan balik perubahan properti memberi tahu Anda ketika nilai efektif properti terikat telah berubah.
Panggilan balik perubahan properti adalah bagian dari metadata properti dependensi. Jika Anda berasal dari kelas yang menentukan properti dependensi, atau menambahkan kelas Anda sebagai pemilik properti dependensi, Anda dapat mengambil alih metadata. Saat mengambil alih metadata, Anda memiliki opsi untuk memberikan referensi baru PropertyChangedCallback . Gunakan callback perubahan properti untuk menjalankan logika yang diperlukan saat nilai properti berubah.
Tidak seperti panggilan balik validasi nilai, panggilan balik perubahan properti memiliki parameter yang menentukan instance DependencyObject, di mana nilai baru diatur. Contoh berikutnya menunjukkan bagaimana panggilan balik yang diubah properti dapat menggunakan DependencyObject referensi instans untuk memicu panggilan balik nilai koerce.
Panggilan balik nilai koerce
Panggilan balik nilai koerce menyediakan cara bagi Anda untuk mendapatkan pemberitahuan ketika nilai efektif properti dependensi akan berubah, sehingga Anda dapat menyesuaikan nilai baru sebelum diterapkan. Selain dipicu oleh sistem properti, Anda dapat memanggil panggilan balik coerce-value dari kode Anda.
Panggilan balik nilai koersi adalah bagian dari metadata properti dependensi. Jika Anda berasal dari kelas yang menentukan properti dependensi, atau menambahkan kelas Anda sebagai pemilik properti dependensi, Anda dapat mengambil alih metadata. Saat mengambil alih metadata, Anda memiliki opsi untuk memberikan referensi ke baru CoerceValueCallback. Gunakan panggilan balik coerce-value untuk mengevaluasi nilai baru dan memaksanya jika diperlukan. Panggilan balik mengembalikan nilai yang dikoersi jika terjadi koersi, jika tidak, panggilan akan mengembalikan nilai baru yang tidak diubah.
Mirip dengan panggilan balik untuk perubahan properti, panggilan balik coerce-value memiliki parameter yang menentukan instans DependencyObject tempat nilai baru ditetapkan. Contoh berikutnya menunjukkan bagaimana panggilan balik nilai koersi dapat menggunakan DependencyObject referensi instans untuk memaksa nilai properti.
Nota
Nilai properti default tidak dapat dipaksakan. Properti dependensi memiliki nilai default yang diatur pada inisialisasi objek, atau saat Anda menghapus nilai lain menggunakan ClearValue.
Korelasi nilai dan panggilan balik perubahan properti dalam kombinasi
Anda dapat membuat dependensi antara properti pada elemen, dengan menggunakan panggilan balik nilai koerce dan panggilan balik yang diubah properti dalam kombinasi. Misalnya, perubahan pada satu properti memaksa pengubahan atau evaluasi ulang properti dependensi lain. Contoh berikutnya menunjukkan skenario umum: tiga properti dependensi yang masing-masing menyimpan nilai saat ini, nilai minimum, dan nilai maksimum elemen UI. Jika nilai maksimum berubah sehingga kurang dari nilai saat ini, nilai saat ini kemudian diatur ke nilai maksimum baru. Dan, jika nilai minimum berubah sehingga lebih besar dari nilai saat ini, nilai saat ini kemudian diatur ke nilai minimum baru. Dalam contoh, PropertyChangedCallback untuk nilai saat ini secara eksplisit memanggil CoerceValueCallback untuk nilai minimum dan maksimum.
public class Gauge2 : Control
{
public Gauge2() : base() { }
// Register a dependency property with the specified property name,
// property type, owner type, property metadata, and callbacks.
public static readonly DependencyProperty CurrentReadingProperty =
DependencyProperty.Register(
name: "CurrentReading",
propertyType: typeof(double),
ownerType: typeof(Gauge2),
typeMetadata: new FrameworkPropertyMetadata(
defaultValue: double.NaN,
flags: FrameworkPropertyMetadataOptions.AffectsMeasure,
propertyChangedCallback: new PropertyChangedCallback(OnCurrentReadingChanged),
coerceValueCallback: new CoerceValueCallback(CoerceCurrentReading)
),
validateValueCallback: new ValidateValueCallback(IsValidReading)
);
// CLR wrapper with get/set accessors.
public double CurrentReading
{
get => (double)GetValue(CurrentReadingProperty);
set => SetValue(CurrentReadingProperty, value);
}
// Validate-value callback.
public static bool IsValidReading(object value)
{
double val = (double)value;
return !val.Equals(double.NegativeInfinity) && !val.Equals(double.PositiveInfinity);
}
// Property-changed callback.
private static void OnCurrentReadingChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
{
depObj.CoerceValue(MinReadingProperty);
depObj.CoerceValue(MaxReadingProperty);
}
// Coerce-value callback.
private static object CoerceCurrentReading(DependencyObject depObj, object value)
{
Gauge2 gauge = (Gauge2)depObj;
double currentVal = (double)value;
currentVal = currentVal < gauge.MinReading ? gauge.MinReading : currentVal;
currentVal = currentVal > gauge.MaxReading ? gauge.MaxReading : currentVal;
return currentVal;
}
// Register a dependency property with the specified property name,
// property type, owner type, property metadata, and callbacks.
public static readonly DependencyProperty MaxReadingProperty = DependencyProperty.Register(
name: "MaxReading",
propertyType: typeof(double),
ownerType: typeof(Gauge2),
typeMetadata: new FrameworkPropertyMetadata(
defaultValue: double.NaN,
flags: FrameworkPropertyMetadataOptions.AffectsMeasure,
propertyChangedCallback: new PropertyChangedCallback(OnMaxReadingChanged),
coerceValueCallback: new CoerceValueCallback(CoerceMaxReading)
),
validateValueCallback: new ValidateValueCallback(IsValidReading)
);
// CLR wrapper with get/set accessors.
public double MaxReading
{
get => (double)GetValue(MaxReadingProperty);
set => SetValue(MaxReadingProperty, value);
}
// Property-changed callback.
private static void OnMaxReadingChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
{
depObj.CoerceValue(MinReadingProperty);
depObj.CoerceValue(CurrentReadingProperty);
}
// Coerce-value callback.
private static object CoerceMaxReading(DependencyObject depObj, object value)
{
Gauge2 gauge = (Gauge2)depObj;
double maxVal = (double)value;
return maxVal < gauge.MinReading ? gauge.MinReading : maxVal;
}
// Register a dependency property with the specified property name,
// property type, owner type, property metadata, and callbacks.
public static readonly DependencyProperty MinReadingProperty = DependencyProperty.Register(
name: "MinReading",
propertyType: typeof(double),
ownerType: typeof(Gauge2),
typeMetadata: new FrameworkPropertyMetadata(
defaultValue: double.NaN,
flags: FrameworkPropertyMetadataOptions.AffectsMeasure,
propertyChangedCallback: new PropertyChangedCallback(OnMinReadingChanged),
coerceValueCallback: new CoerceValueCallback(CoerceMinReading)
),
validateValueCallback: new ValidateValueCallback(IsValidReading));
// CLR wrapper with get/set accessors.
public double MinReading
{
get => (double)GetValue(MinReadingProperty);
set => SetValue(MinReadingProperty, value);
}
// Property-changed callback.
private static void OnMinReadingChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
{
depObj.CoerceValue(MaxReadingProperty);
depObj.CoerceValue(CurrentReadingProperty);
}
// Coerce-value callback.
private static object CoerceMinReading(DependencyObject depObj, object value)
{
Gauge2 gauge = (Gauge2)depObj;
double minVal = (double)value;
return minVal > gauge.MaxReading ? gauge.MaxReading : minVal;
}
}
Public Class Gauge2
Inherits Control
Public Sub New()
MyBase.New()
End Sub
' Register a dependency property with the specified property name,
' property type, owner type, property metadata, And callbacks.
Public Shared ReadOnly CurrentReadingProperty As DependencyProperty =
DependencyProperty.Register(
name:="CurrentReading",
propertyType:=GetType(Double),
ownerType:=GetType(Gauge2),
typeMetadata:=New FrameworkPropertyMetadata(
defaultValue:=Double.NaN,
flags:=FrameworkPropertyMetadataOptions.AffectsMeasure,
propertyChangedCallback:=New PropertyChangedCallback(AddressOf OnCurrentReadingChanged),
coerceValueCallback:=New CoerceValueCallback(AddressOf CoerceCurrentReading)),
validateValueCallback:=New ValidateValueCallback(AddressOf IsValidReading))
' CLR wrapper with get/set accessors.
Public Property CurrentReading As Double
Get
Return GetValue(CurrentReadingProperty)
End Get
Set(value As Double)
SetValue(CurrentReadingProperty, value)
End Set
End Property
' Validate-value callback.
Public Shared Function IsValidReading(value As Object) As Boolean
Dim val As Double = value
Return Not val.Equals(Double.NegativeInfinity) AndAlso Not val.Equals(Double.PositiveInfinity)
End Function
' Property-changed callback.
Private Shared Sub OnCurrentReadingChanged(depObj As DependencyObject, e As DependencyPropertyChangedEventArgs)
depObj.CoerceValue(MinReadingProperty)
depObj.CoerceValue(MaxReadingProperty)
End Sub
' Coerce-value callback.
Private Shared Function CoerceCurrentReading(depObj As DependencyObject, value As Object) As Object
Dim gauge As Gauge2 = CType(depObj, Gauge2)
Dim currentVal As Double = value
currentVal = If(currentVal < gauge.MinReading, gauge.MinReading, currentVal)
currentVal = If(currentVal > gauge.MaxReading, gauge.MaxReading, currentVal)
Return currentVal
End Function
Public Shared ReadOnly MaxReadingProperty As DependencyProperty =
DependencyProperty.Register(
name:="MaxReading",
propertyType:=GetType(Double),
ownerType:=GetType(Gauge2),
typeMetadata:=New FrameworkPropertyMetadata(
defaultValue:=Double.NaN,
flags:=FrameworkPropertyMetadataOptions.AffectsMeasure,
propertyChangedCallback:=New PropertyChangedCallback(AddressOf OnMaxReadingChanged),
coerceValueCallback:=New CoerceValueCallback(AddressOf CoerceMaxReading)),
validateValueCallback:=New ValidateValueCallback(AddressOf IsValidReading))
' CLR wrapper with get/set accessors.
Public Property MaxReading As Double
Get
Return GetValue(MaxReadingProperty)
End Get
Set(value As Double)
SetValue(MaxReadingProperty, value)
End Set
End Property
' Property-changed callback.
Private Shared Sub OnMaxReadingChanged(depObj As DependencyObject, e As DependencyPropertyChangedEventArgs)
depObj.CoerceValue(MinReadingProperty)
depObj.CoerceValue(CurrentReadingProperty)
End Sub
' Coerce-value callback.
Private Shared Function CoerceMaxReading(depObj As DependencyObject, value As Object) As Object
Dim gauge As Gauge2 = CType(depObj, Gauge2)
Dim maxVal As Double = value
Return If(maxVal < gauge.MinReading, gauge.MinReading, maxVal)
End Function
' Register a dependency property with the specified property name,
' property type, owner type, property metadata, And callbacks.
Public Shared ReadOnly MinReadingProperty As DependencyProperty =
DependencyProperty.Register(
name:="MinReading",
propertyType:=GetType(Double),
ownerType:=GetType(Gauge2),
typeMetadata:=New FrameworkPropertyMetadata(
defaultValue:=Double.NaN,
flags:=FrameworkPropertyMetadataOptions.AffectsMeasure,
propertyChangedCallback:=New PropertyChangedCallback(AddressOf OnMinReadingChanged),
coerceValueCallback:=New CoerceValueCallback(AddressOf CoerceMinReading)),
validateValueCallback:=New ValidateValueCallback(AddressOf IsValidReading))
' CLR wrapper with get/set accessors.
Public Property MinReading As Double
Get
Return GetValue(MinReadingProperty)
End Get
Set(value As Double)
SetValue(MinReadingProperty, value)
End Set
End Property
' Property-changed callback.
Private Shared Sub OnMinReadingChanged(depObj As DependencyObject, e As DependencyPropertyChangedEventArgs)
depObj.CoerceValue(MaxReadingProperty)
depObj.CoerceValue(CurrentReadingProperty)
End Sub
' Coerce-value callback.
Private Shared Function CoerceMinReading(depObj As DependencyObject, value As Object) As Object
Dim gauge As Gauge2 = CType(depObj, Gauge2)
Dim minVal As Double = value
Return If(minVal > gauge.MaxReading, gauge.MaxReading, minVal)
End Function
End Class
Skenario panggilan balik tingkat lanjut
Batasan dan nilai yang diinginkan
Jika nilai properti dependensi yang ditetapkan secara lokal diubah melalui koersi, nilai yang ditetapkan secara lokal yang tidak berubah dipertahankan sebagai nilai yang diinginkan. Jika koersi didasarkan pada nilai properti lain, sistem properti akan mengevaluasi kembali koersi secara dinamis setiap kali nilai lain berubah. Dalam batasan paksaan, sistem properti akan menerapkan nilai yang paling dekat dengan nilai yang diinginkan. Jika kondisi koersi tidak lagi berlaku, sistem properti akan memulihkan nilai yang diinginkan—dengan asumsi tidak ada nilai prioritas yang lebih tinggi yang aktif. Contoh berikut menguji koersi dalam nilai saat ini, nilai minimum, dan skenario nilai maksimum.
public static void TestCoercionBehavior()
{
Gauge2 gauge = new()
{
// Set initial values.
MinReading = 0,
MaxReading = 10,
CurrentReading = 5
};
Debug.WriteLine($"Test current/min/max values scenario:");
// Current reading is not coerced.
Debug.WriteLine($"Current reading: " +
$"{gauge.CurrentReading} (min: {gauge.MinReading}, max: {gauge.MaxReading})");
// Current reading is coerced to max value.
gauge.MaxReading = 3;
Debug.WriteLine($"Current reading: " +
$"{gauge.CurrentReading} (min: {gauge.MinReading}, max: {gauge.MaxReading})");
// Current reading is coerced, but tracking back to the desired value.
gauge.MaxReading = 4;
Debug.WriteLine($"Current reading: " +
$"{gauge.CurrentReading} (min: {gauge.MinReading}, max: {gauge.MaxReading})");
// Current reading reverts to the desired value.
gauge.MaxReading = 10;
Debug.WriteLine($"Current reading: " +
$"{gauge.CurrentReading} (min: {gauge.MinReading}, max: {gauge.MaxReading})");
// Current reading remains at the desired value.
gauge.MinReading = 5;
gauge.MaxReading = 5;
Debug.WriteLine($"Current reading: " +
$"{gauge.CurrentReading} (min: {gauge.MinReading}, max: {gauge.MaxReading})");
// Current reading: 5 (min=0, max=10)
// Current reading: 3 (min=0, max=3)
// Current reading: 4 (min=0, max=4)
// Current reading: 5 (min=0, max=10)
// Current reading: 5 (min=5, max=5)
}
Public Shared Sub TestCoercionBehavior()
' Set initial values.
Dim gauge As New Gauge2 With {
.MinReading = 0,
.MaxReading = 10,
.CurrentReading = 5
}
Debug.WriteLine($"Test current/min/max values scenario:")
' Current reading is not coerced.
Debug.WriteLine($"Current reading: " &
$"{gauge.CurrentReading} (min={gauge.MinReading}, max={gauge.MaxReading})")
' Current reading is coerced to max value.
gauge.MaxReading = 3
Debug.WriteLine($"Current reading: " &
$"{gauge.CurrentReading} (min={gauge.MinReading}, max={gauge.MaxReading})")
' Current reading is coerced, but tracking back to the desired value.
gauge.MaxReading = 4
Debug.WriteLine($"Current reading: " &
$"{gauge.CurrentReading} (min={gauge.MinReading}, max={gauge.MaxReading})")
' Current reading reverts to the desired value.
gauge.MaxReading = 10
Debug.WriteLine($"Current reading: " &
$"{gauge.CurrentReading} (min={gauge.MinReading}, max={gauge.MaxReading})")
' Current reading remains at the desired value.
gauge.MinReading = 5
gauge.MaxReading = 5
Debug.WriteLine($"Current reading: " &
$"{gauge.CurrentReading} (min={gauge.MinReading}, max={gauge.MaxReading})")
' Current reading: 5 (min=0, max=10)
' Current reading: 3 (min=0, max=3)
' Current reading: 4 (min=0, max=4)
' Current reading: 5 (min=0, max=10)
' Current reading: 5 (min=5, max=5)
End Sub
Skenario dependensi yang cukup kompleks dapat terjadi ketika Anda memiliki beberapa properti yang bergantung satu sama lain secara melingkar. Secara teknis, tidak ada yang salah dengan dependensi kompleks—kecuali bahwa sejumlah besar evaluasi ulang dapat mengurangi performa. Selain itu, dependensi kompleks yang terekspos di UI mungkin membingungkan pengguna. Perlakukan PropertyChangedCallback dan CoerceValueCallback sejelas mungkin, dan jangan terlalu membatasi.
Batalkan perubahan nilai
Dengan mengembalikan UnsetValue dari CoerceValueCallback, Anda dapat menolak perubahan nilai properti. Mekanisme ini berguna ketika perubahan nilai properti dimulai secara asinkron, tetapi ketika diterapkan tidak lagi valid untuk status objek saat ini. Skenario lain mungkin untuk secara selektif menekan perubahan nilai berdasarkan asalnya. Dalam contoh berikut, CoerceValueCallback memanggil GetValueSource metode , yang mengembalikan ValueSource struktur dengan BaseValueSource enumerasi yang mengidentifikasi sumber nilai baru.
// Coerce-value callback.
private static object CoerceCurrentReading(DependencyObject depObj, object value)
{
// Get value source.
ValueSource valueSource =
DependencyPropertyHelper.GetValueSource(depObj, CurrentReadingProperty);
// Reject any property value change that's a locally set value.
return valueSource.BaseValueSource == BaseValueSource.Local ?
DependencyProperty.UnsetValue : value;
}
' Coerce-value callback.
Private Shared Function CoerceCurrentReading(depObj As DependencyObject, value As Object) As Object
' Get value source.
Dim valueSource As ValueSource =
DependencyPropertyHelper.GetValueSource(depObj, CurrentReadingProperty)
' Reject any property value that's a locally set value.
Return If(valueSource.BaseValueSource = BaseValueSource.Local, DependencyProperty.UnsetValue, value)
End Function
Lihat juga
.NET Desktop feedback