Callbacks en validatie van afhankelijkheidseigenschappen (WPF .NET)
In dit artikel wordt beschreven hoe u een afhankelijkheidseigenschap definieert en callbacks voor afhankelijkheden implementeert. De callbacks ondersteunen waardevalidatie, waardecodering en andere logica die nodig is wanneer een eigenschapswaarde wordt gewijzigd.
Voorwaarden
In het artikel wordt ervan uitgegaan dat u basiskennis hebt van afhankelijkheidseigenschappen en dat u overzicht van eigenschappen van afhankelijkheden hebt gelezen. Als u de voorbeelden in dit artikel wilt volgen, helpt dit als u bekend bent met Extensible Application Markup Language (XAML) en weet hoe u WPF-toepassingen schrijft.
Callbacks voor validatiewaarden
Callbacks voor validatiewaarden bieden een manier om te controleren of een nieuwe waarde van een afhankelijkheidseigenschap geldig is voordat deze wordt toegepast door het eigenschapssysteem. Deze callback genereert een uitzondering als de waarde niet voldoet aan de validatiecriteria.
Callbacks voor validatiewaarden kunnen slechts eenmaal worden toegewezen aan een afhankelijkheidseigenschap tijdens de registratie van eigenschappen. Bij het registreren van een afhankelijkheidseigenschap kunt u een ValidateValueCallback verwijzing doorgeven naar de Register(String, Type, Type, PropertyMetadata, ValidateValueCallback) methode. Callbacks voor validatiewaarden maken geen deel uit van eigenschapsmetagegevens en kunnen niet worden overschreven.
De effectieve waarde van een afhankelijkheidseigenschap is de toegepaste waarde. De effectieve waarde wordt bepaald door de eigenschapswaardepreferentie van wanneer er meerdere eigenschapsgebaseerde invoeren zijn. Als een callback van validatiewaarden is geregistreerd voor een afhankelijkheidseigenschap, roept het eigenschapssysteem de callback van de validatiewaarde aan bij waardewijziging, waarbij de nieuwe waarde als object wordt doorgegeven. In de callback kunt u het waardeobject terugzetten naar het type dat is geregistreerd bij het eigenschappensysteem en vervolgens de validatielogica erop uitvoeren. De callback retourneert true
als de waarde geldig is voor de eigenschap, anders false
.
Als een callback voor validatiewaarden false
retourneert, wordt er een uitzondering gegenereerd en wordt de nieuwe waarde niet toegepast. Applicatieontwikkelaars moeten voorbereid zijn om deze uitzonderingen af te handelen. Een veelvoorkomend gebruik van callbacks voor validatiewaarden is het valideren van opsommingswaarden of het beperken van numerieke waarden wanneer ze metingen met limieten vertegenwoordigen. Callbacks voor validatiewaarden worden in verschillende scenario's door het eigenschapssysteem aangeroepen, waaronder:
- Object initialisatie, waarmee een standaardwaarde wordt toegepast tijdens het maken.
- Programmatische aanroepen naar SetValue.
- Metagegevens overschrijven die een nieuwe standaardwaarde opgeven.
Callbacks voor validatiewaarden hebben geen parameter die de DependencyObject instantie specificeert waarop de nieuwe waarde wordt ingesteld. Alle exemplaren van een DependencyObject
hebben dezelfde callback voor validatiewaarden, daarom kan deze niet worden gebruikt om exemplaar-specifieke scenario's te valideren. Zie ValidateValueCallbackvoor meer informatie.
In het volgende voorbeeld ziet u hoe u kunt voorkomen dat een eigenschap, getypt als Double, wordt ingesteld op PositiveInfinity of 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
Callbacks die door eigenschappen zijn gewijzigd
Callbacks die door eigenschappen zijn gewijzigd, melden u wanneer de effectieve waarde van een afhankelijkheidseigenschap is gewijzigd.
Callbacks die door eigenschappen zijn gewijzigd, maken deel uit van metagegevens van afhankelijkheden. Als u bent afgeleid van een klasse die een afhankelijkheidseigenschap definieert of uw klasse toevoegt als eigenaar van een afhankelijkheidseigenschap, kunt u de metagegevens overschrijven. Wanneer u metagegevens overschrijft, hebt u de mogelijkheid om een nieuwe PropertyChangedCallback verwijzing op te geven. Gebruik een door een eigenschap gewijzigd callback om logica uit te voeren die nodig is wanneer een eigenschapswaarde wordt gewijzigd.
In tegenstelling tot callbacks voor validatiewaarden hebben callbacks die door eigenschappen zijn gewijzigd een parameter die de DependencyObject instantie aangeeft waarop de nieuwe waarde is ingesteld. In het volgende voorbeeld ziet u hoe een door een eigenschap gewijzigde callback de DependencyObject
exemplaarverwijzing kan gebruiken om callbacks voor coerce-waarde te activeren.
Callbacks met coerce-waarde
Callbacks voor coerce-waarden bieden een manier om u op de hoogte te stellen wanneer de effectieve waarde van een afhankelijkheidseigenschap wordt gewijzigd, zodat u de nieuwe waarde kunt aanpassen voordat deze wordt toegepast. U kunt, naast dat het eigenschapssysteem ze activeert, zelf 'coerce-value' callbacks aanroepen in uw code.
Callbacks voor coerce-value vormen onderdeel van de metagegevens van dependency-properties. Als u bent afgeleid van een klasse die een afhankelijkheidseigenschap definieert of uw klasse toevoegt als eigenaar van een afhankelijkheidseigenschap, kunt u de metagegevens overschrijven. Wanneer u de metagegevens overschrijft, kunt u een verwijzing naar een nieuwe CoerceValueCallbackopgeven. Gebruik een coerce-value callback om nieuwe waarden te evalueren en indien nodig bij te stellen. De callback retourneert de gecoerceerde waarde als er sprake is van dwang, anders wordt de ongewijzigde nieuwe waarde geretourneerd.
Net als bij callbacks die door eigenschappen zijn gewijzigd, hebben callbacks met coerce-waarde een parameter die het DependencyObject exemplaar aangeeft waarop de nieuwe waarde is ingesteld. In het volgende voorbeeld ziet u hoe een coerce-value callback een DependencyObject
exemplaarverwijzing kan gebruiken om eigenschapswaarden te forceren.
Notitie
Standaardeigenschapswaarden kunnen niet worden afgedwongen. Een afhankelijkheidseigenschap wordt de standaardwaarde ingesteld bij objectinitialisatie, of wanneer u andere waarden wist met behulp van ClearValue.
Coerce-value en eigenschap-veranderd callbacks in combinatie
U kunt afhankelijkheden tussen eigenschappen van een element maken door gebruik te maken van geforceerde waarde callbacks en eigenschap-veranderde callbacks in combinatie. Bijvoorbeeld, wijzigingen in de ene eigenschap dwingen tot heroverweging of herbeoordeling bij een andere afhankelijkheidseigenschap. In het volgende voorbeeld ziet u een veelvoorkomend scenario: drie afhankelijkheidseigenschappen waarin respectievelijk de huidige waarde, minimumwaarde en maximumwaarde van een UI-element worden opgeslagen. Als de maximumwaarde verandert zodat deze kleiner is dan de huidige waarde, wordt de huidige waarde ingesteld op de nieuwe maximumwaarde. En als de minimumwaarde verandert zodat deze groter is dan de huidige waarde, wordt de huidige waarde ingesteld op de nieuwe minimumwaarde. In het voorbeeld roept de PropertyChangedCallback voor de huidige waarde expliciet de CoerceValueCallback aan voor de minimum- en maximumwaarden.
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
Geavanceerde callback-scenario's
Beperkingen en gewenste waarden
Als een lokaal ingestelde waarde van een afhankelijkheidseigenschap wordt gewijzigd via dwang, blijft de ongewijzigde lokaal ingestelde waarde behouden als de gewenste waarde . Wanneer de beperking is gebaseerd op andere eigenschapswaarden, zal het eigenschapssysteem de beperking dynamisch herevalueren telkens wanneer die andere waarden veranderen. Binnen de beperkingen van de dwang past het eigenschappensysteem een waarde toe die het dichtst bij de gewenste waarde ligt. Als de voorwaarde voor dwang niet meer van toepassing is, herstelt het eigenschapssysteem de gewenste waarde, ervan uitgaande dat er geen hogere prioriteit waarde actief is. In het volgende voorbeeld wordt de dwang getest in de huidige waarde, de minimumwaarde en het maximumwaardescenario.
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
Er kunnen redelijk complexe afhankelijkheidsscenario's optreden wanneer u meerdere eigenschappen hebt die afhankelijk zijn van elkaar op een kringvormige manier. Technisch gezien is er niets mis met complexe afhankelijkheden, behalve dat een groot aantal nieuwe evaluaties de prestaties kan verminderen. Complexe afhankelijkheden die in de gebruikersinterface worden weergegeven, kunnen gebruikers ook verwarren. Behandel PropertyChangedCallback en CoerceValueCallback zo ondubbelzinnig mogelijk en leg er geen te strenge beperkingen op.
Wijzigingen in waarde annuleren
Als u UnsetValue retourneert vanuit een CoerceValueCallback, kunt u een wijziging van de eigenschapswaarde negeren. Dit mechanisme is handig wanneer een wijziging van de eigenschapswaarde asynchroon wordt gestart, maar wanneer deze wordt toegepast, niet meer geldig is voor de huidige objectstatus. Een ander scenario kan zijn om selectief een waardewijziging te onderdrukken op basis van waar deze vandaan komt. In het volgende voorbeeld roept de CoerceValueCallback
de methode GetValueSource aan, waarmee een ValueSource structuur wordt geretourneerd met een BaseValueSource opsomming waarmee de bron van de nieuwe waarde wordt geïdentificeerd.
// 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
Zie ook
.NET Desktop feedback