Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Artikel wird beschrieben, wie Sie eine Abhängigkeitseigenschaft definieren und Rückrufe für Abhängigkeitseigenschaften implementieren. Die Rückrufe unterstützen die Wertüberprüfung, die Wertekoersion und andere Logik, die erforderlich ist, wenn sich ein Eigenschaftswert ändert.
Voraussetzungen
In diesem Artikel wird davon ausgegangen, dass Sie über grundlegende Kenntnisse von Abhängigkeitseigenschaften verfügen und eine Übersicht über Abhängigkeitseigenschaften gelesen haben. Um den Beispielen in diesem Artikel zu folgen, hilft es Ihnen, wenn Sie mit Extensible Application Markup Language (XAML) vertraut sind und wissen, wie WPF-Anwendungen geschrieben werden.
Wertvalidierungsrückrufe
Mit Überprüfungswertrückrufen können Sie überprüfen, ob ein neuer Abhängigkeitseigenschaftswert gültig ist, bevor er vom Eigenschaftensystem angewendet wird. Dieser Rückruf löst eine Ausnahme aus, wenn der Wert nicht den Überprüfungskriterien entspricht.
Validierungs-Wert-Rückrufe können einer Abhängigkeitseigenschaft nur einmal zugewiesen werden, und zwar während der Eigenschaftsregistrierung. Beim Registrieren einer Abhängigkeitseigenschaft haben Sie die Möglichkeit, einen ValidateValueCallback Verweis auf die Register(String, Type, Type, PropertyMetadata, ValidateValueCallback) Methode zu übergeben. Überprüfungswertrückrufe sind nicht Teil von Eigenschaftsmetadaten und können nicht überschrieben werden.
Der effektive Wert einer Abhängigkeitseigenschaft ist der angewendete Wert. Der effektive Wert wird durch Eigenschaftswertrangfolge bestimmt, wenn mehrere eigenschaftsbasierte Eingaben vorhanden sind. Wenn ein Wertvalidierungsrückruf für eine Abhängigkeitseigenschaft registriert ist, wird das Eigenschaftensystem bei einer Änderung des Wertes diesen Rückruf aufrufen und den neuen Wert als Objekt übergeben. Innerhalb des Rückrufs können Sie das Wertobjekt wieder in den Typ umwandeln, der beim Eigenschaftensystem registriert ist, und dann die Validierungslogik darauf ausführen. Der Rückruf gibt zurück true
, wenn der Wert für die Eigenschaft gültig ist, andernfalls false
.
Wenn ein Rückruf zur Wertevalidierung den Wert false
zurückgibt, wird eine Ausnahme ausgelöst und der neue Wert nicht angewendet. Anwendungsautoren müssen darauf vorbereitet sein, diese Ausnahmen zu behandeln. Eine häufige Verwendung von Überprüfungswertrückrufen ist das Validieren von Enumerationswerten oder das Einschränken numerischer Werte, wenn sie Maße darstellen, die Grenzwerte aufweisen. Überprüfungswertrückrufe werden vom Eigenschaftensystem in verschiedenen Szenarien aufgerufen, darunter:
- Objektinitialisierung, die zur Erstellungszeit einen Standardwert anwendet.
- Programmatische Aufrufe an SetValue.
- Metadatenüberschreibungen, die einen neuen Standardwert angeben.
Validate-Value-Rückrufe verfügen nicht über einen Parameter, der die Instanz angibt, auf der DependencyObject der neue Wert festgelegt wird. Alle Instanzen einer DependencyObject
haben denselben Validierungs-Wert-Rückruf, sodass er nicht zum Überprüfen instanzspezifischer Szenarien verwendet werden kann. Weitere Informationen finden Sie unter ValidateValueCallback.
Das folgende Beispiel zeigt, wie Sie verhindern, dass eine Eigenschaft, die als Double eingegeben wurde, auf PositiveInfinity oder NegativeInfinity gesetzt wird.
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
Rückrufe mit Eigenschaftsänderung
Eigenschaftsänderungs-Callbacks benachrichtigen Sie, wenn sich der effektive Wert einer Abhängigkeitseigenschaft geändert hat.
Eigenschaftsänderungsrückrufe sind Teil der Metadaten einer abhängigen Eigenschaft. Wenn Sie von einer Klasse abgeleitet werden, die eine Abhängigkeitseigenschaft definiert, oder Ihre Klasse als Besitzer einer Abhängigkeitseigenschaft hinzufügen, können Sie die Metadaten überschreiben. Beim Überschreiben von Metadaten haben Sie die Möglichkeit, einen neuen PropertyChangedCallback Verweis bereitzustellen. Verwenden Sie einen Rückruf bei Eigenschaftsänderung, um die notwendige Logik auszuführen, wenn sich ein Eigenschaftswert ändert.
Im Gegensatz zu validate-value-Rückrufen haben Eigenschaftsänderungsrückrufe einen Parameter, der die Instanz angibt, auf der der neue Wert festgelegt wird. Das nächste Beispiel zeigt, wie ein Eigenschaftsänderungsrückruf den DependencyObject
Instanzverweis verwenden kann, um Rückrufe zur Wertzwangszuweisung auszulösen.
Coerce-Wertrückrufe
Coerce-Value-Rückrufe bieten ihnen eine Möglichkeit, benachrichtigt zu werden, wenn der effektive Wert einer Abhängigkeitseigenschaft geändert werden soll, damit Sie den neuen Wert anpassen können, bevor er angewendet wird. Zusätzlich zur Aktivierung durch das Eigenschaftensystem können Sie Coerce-Wert-Rückruffunktionen aus Ihrem Code aufrufen.
Rückruffunktionen für Wertzwang sind Teil der Metadaten von Abhängigkeitseigenschaften. Wenn Sie von einer Klasse abgeleitet werden, die eine Abhängigkeitseigenschaft definiert, oder Ihre Klasse als Besitzer einer Abhängigkeitseigenschaft hinzufügen, können Sie die Metadaten überschreiben. Beim Ändern der Metadaten haben Sie die Möglichkeit, einen Verweis auf eine neue CoerceValueCallback bereitzustellen. Verwenden Sie einen Callback zur Wertanpassung, um neue Werte auszuwerten und diese bei Bedarf anzupassen. Der Rückruf gibt den koercierten Wert zurück, wenn der Koersionswert aufgetreten ist, andernfalls wird der unveränderte neue Wert zurückgegeben.
Ähnlich wie Eigenschaftsänderungs-Rückrufe weisen Zwangswertrückrufe einen Parameter auf, der die Instanz angibt, auf der der neue Wert DependencyObject gesetzt wird. Das nächste Beispiel zeigt, wie ein Wertzwang-Callback einen DependencyObject
-Instanzverweis verwenden kann, um Eigenschaftswerte zu erzwingen.
Hinweis
Standardwerte von Eigenschaften können nicht erzwungen werden. Eine Abhängigkeitseigenschaft wird auf ihren Standardwert gesetzt bei der Objektinitialisierung oder wenn Sie andere Werte mit ClearValue löschen.
Zwängungswert- und Eigenschaftsänderungs-Benachrichtigungen in Kombination
Sie können Abhängigkeiten zwischen Eigenschaften für ein Element erstellen, indem Sie Rückrufe mit Wertanpassung und Eigenschaftsänderungsrückrufe verwenden. Änderungen in einer Eigenschaft erzwingen die Erzwingung oder erneute Auswertung bei einer anderen abhängigen Eigenschaft. Das nächste Beispiel zeigt ein gängiges Szenario: drei Abhängigkeitseigenschaften, die den aktuellen Wert, den Minimalwert und den Maximalwert eines UI-Elements speichern. Wenn sich der Maximalwert ändert, sodass er kleiner als der aktuelle Wert ist, wird der aktuelle Wert auf den neuen Maximalwert festgelegt. Und wenn sich der Mindestwert ändert, sodass er größer als der aktuelle Wert ist, wird der aktuelle Wert auf den neuen Minimalwert festgelegt. Im Beispiel ruft der PropertyChangedCallback aktuelle Wert explizit die CoerceValueCallback Mindest- und Höchstwerte auf.
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
Erweiterte Rückrufszenarien
Einschränkungen und gewünschte Werte
Wenn ein lokal festgelegter Wert einer Abhängigkeitseigenschaft durch Koersion geändert wird, wird der unveränderte lokal festgelegte Wert als der gewünschte Wert beibehalten. Wenn die Koerzierung auf anderen Eigenschaftswerten basiert, wird das Eigenschaftensystem die Koerzierung dynamisch neu bewerten, sobald sich diese anderen Werte ändern. Innerhalb der Einschränkungen des Koersions wendet das Eigenschaftensystem einen Wert an, der dem gewünschten Wert am nächsten kommt. Sollte die Koersionsbedingung nicht mehr angewendet werden, stellt das Eigenschaftensystem den gewünschten Wert wieder her – vorausgesetzt, kein höherer Rangfolgewert ist aktiv. Im folgenden Beispiel wird die Koersion im aktuellen Wert, dem Minimalwert und dem Maximalwertszenario getestet.
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
Ziemlich komplexe Abhängigkeitsszenarien können auftreten, wenn Sie mehrere Eigenschaften haben, die auf zirkuläre Weise voneinander abhängig sind. Technisch gesehen gibt es nichts Falsches mit komplexen Abhängigkeiten – mit der Ausnahme, dass eine große Anzahl von Neubewertungen die Leistung reduzieren kann. Außerdem können komplexe Abhängigkeiten, die in der Benutzeroberfläche verfügbar gemacht werden, Benutzer verwirren. Behandeln PropertyChangedCallback und CoerceValueCallback so eindeutig wie möglich, und nicht übermäßig einschränken.
Abbrechen von Wertänderungen
Durch die UnsetValue Rückgabe von einem CoerceValueCallback, können Sie eine Änderung des Eigenschaftswerts ablehnen. Dieser Mechanismus ist nützlich, wenn eine Eigenschaftswertänderung asynchron initiiert wird, aber wenn sie angewendet wird, ist sie für den aktuellen Objektzustand nicht mehr gültig. Ein weiteres Szenario kann sein, eine Wertänderung basierend auf dem Ursprungsort selektiv zu unterdrücken. Im folgenden Beispiel ruft die CoerceValueCallback
GetValueSource Methode auf, die eine Struktur mit einer ValueSourceBaseValueSource Aufzählung zurückgibt, die die Quelle des neuen Werts identifiziert.
// 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
Siehe auch
.NET Desktop feedback