Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Het ObservableProperty type is een kenmerk waarmee waarneembare eigenschappen kunnen worden gegenereerd op basis van geannoteerde velden. Het doel ervan is om de hoeveelheid boilerplatecode die nodig is om observeerbare eigenschappen te definiëren, aanzienlijk te verminderen.
Note
Om te kunnen werken, moeten geannoteerde velden zich in een gedeeltelijke klasse met de benodigde INotifyPropertyChanged infrastructuur bevindt. Als het om een genest type gaat, moeten alle typen in de declaratie-syntaxisboom ook als partial worden gemarkeerd. Als u dat niet doet, leidt dat tot compileerfouten, omdat de generator geen andere partiële declaratie van dat type kan genereren met de gevraagde observeerbare eigenschap.
Platform-API’s:
ObservableProperty,NotifyPropertyChangedFor,NotifyCanExecuteChangedFor,NotifyDataErrorInfo,NotifyPropertyChangedRecipients,ICommand,IRelayCommand, ObservableValidator,PropertyChangedMessage<T>,IMessenger
Hoe werkt het?
Het ObservableProperty kenmerk kan worden gebruikt om aantekeningen te maken op een veld in een gedeeltelijk type, zoals:
[ObservableProperty]
private string? name;
En er wordt een waarneembare eigenschap als volgt gegenereerd:
public string? Name
{
get => name;
set => SetProperty(ref name, value);
}
Dit gebeurt ook met een geoptimaliseerde implementatie, dus het eindresultaat zal nog sneller zijn.
Note
De naam van de gegenereerde eigenschap wordt gemaakt op basis van de veldnaam. De generator gaat ervan uit dat het veld de naam lowerCamel, _lowerCamel of m_lowerCamel heeft. Het veld transformeert deze om UpperCamel om de juiste naamconventies voor .NET te volgen. De resulterende eigenschap heeft altijd openbare accessors, maar het veld kan met elk zichtbaarheidsniveau worden gedeclareerd (private wordt aanbevolen).
Code uitvoeren bij wijzigingen
De gegenereerde code is eigenlijk iets complexer dan dit, en de reden hiervoor is dat er ook enkele methoden worden weergegeven die u kunt implementeren om te koppelen aan de meldingslogica en extra logica uitvoeren wanneer de eigenschap op het punt staat te worden bijgewerkt en direct nadat deze is bijgewerkt, indien nodig. Dat wil gezegd, de gegenereerde code is vergelijkbaar met deze:
public string? Name
{
get => name;
set
{
if (!EqualityComparer<string?>.Default.Equals(name, value))
{
string? oldValue = name;
OnNameChanging(value);
OnNameChanging(oldValue, value);
OnPropertyChanging();
name = value;
OnNameChanged(value);
OnNameChanged(oldValue, value);
OnPropertyChanged();
}
}
}
partial void OnNameChanging(string? value);
partial void OnNameChanged(string? value);
partial void OnNameChanging(string? oldValue, string? newValue);
partial void OnNameChanged(string? oldValue, string? newValue);
Hiermee kunt u een van deze methoden implementeren om extra code in te voeren. De eerste twee zijn handig wanneer u bepaalde logica wilt uitvoeren die alleen hoeft te verwijzen naar de nieuwe waarde waarop de eigenschap is ingesteld. De andere twee zijn handig wanneer u complexere logica hebt die ook een bepaalde status moet bijwerken op zowel de oude als de nieuwe waarde die wordt ingesteld.
Hier volgt bijvoorbeeld een voorbeeld van hoe de eerste twee overbelastingen kunnen worden gebruikt:
[ObservableProperty]
private string? name;
partial void OnNameChanging(string? value)
{
Console.WriteLine($"Name is about to change to {value}");
}
partial void OnNameChanged(string? value)
{
Console.WriteLine($"Name has changed to {value}");
}
Hier volgt een voorbeeld van hoe de andere twee overbelastingen kunnen worden gebruikt:
[ObservableProperty]
private ChildViewModel? selectedItem;
partial void OnSelectedItemChanging(ChildViewModel? oldValue, ChildViewModel? newValue)
{
if (oldValue is not null)
{
oldValue.IsSelected = false;
}
if (newValue is not null)
{
newValue.IsSelected = true;
}
}
U kunt alleen een aantal methoden implementeren onder de methoden die beschikbaar zijn of geen van deze methoden. Als ze niet worden geïmplementeerd (of als er slechts één is), worden de hele aanroep(en) alleen verwijderd door de compiler, zodat er helemaal geen prestatietreffers zijn voor gevallen waarin deze extra functionaliteit niet vereist is.
Note
De gegenereerde methoden zijn gedeeltelijke methoden zonder implementatie, wat betekent dat als u ervoor kiest om ze te implementeren, u geen expliciete toegankelijkheid voor deze methoden kunt opgeven. Dat wil zeggen, implementaties van deze methoden moeten ook worden gedeclareerd als enkel partial-methoden, en ze hebben altijd impliciet private toegankelijkheid. Als u een expliciete toegankelijkheid probeert toe te voegen (bijvoorbeeld toevoegen public of private), treedt er een fout op, omdat dat niet is toegestaan in C#.
Afhankelijke eigenschappen informeren
Stel dat u een eigenschap FullName hebt waarvoor u een melding wilt genereren telkens wanneer Name verandert. U kunt dit doen met behulp van het NotifyPropertyChangedFor kenmerk, zoals:
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(FullName))]
private string? name;
Dit resulteert in een gegenereerde eigenschap die gelijk is aan deze:
public string? Name
{
get => name;
set
{
if (SetProperty(ref name, value))
{
OnPropertyChanged("FullName");
}
}
}
Afhankelijke opdrachten melden
Stel dat u een opdracht hebt waarvan de uitvoeringsstatus afhankelijk was van de waarde van deze eigenschap. Dat wil zeggen, telkens wanneer de eigenschap verandert, moet de uitvoeringsstatus van het commando worden geïnvalideerd en opnieuw worden bepaald. Met andere woorden, ICommand.CanExecuteChanged moet opnieuw worden verhoogd. U kunt dit bereiken met behulp van het NotifyCanExecuteChangedFor kenmerk:
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(MyCommand))]
private string? name;
Dit resulteert in een gegenereerde eigenschap die gelijk is aan deze:
public string? Name
{
get => name;
set
{
if (SetProperty(ref name, value))
{
MyCommand.NotifyCanExecuteChanged();
}
}
}
Om dit te laten werken, moet de doelopdracht een eigenschap IRelayCommand zijn.
Validatie van eigenschap aanvragen
Als de eigenschap wordt gedeclareerd in een type dat wordt overgenomen van ObservableValidator, is het ook mogelijk om er aantekeningen aan te maken met eventuele validatiekenmerken en vervolgens de gegenereerde setter aan te vragen om validatie voor die eigenschap te activeren. Dit kan worden bereikt met het NotifyDataErrorInfo kenmerk:
[ObservableProperty]
[NotifyDataErrorInfo]
[Required]
[MinLength(2)] // Any other validation attributes too...
private string? name;
Dit leidt ertoe dat de volgende eigenschap wordt gegenereerd:
public string? Name
{
get => name;
set
{
if (SetProperty(ref name, value))
{
ValidateProperty(value, "Value2");
}
}
}
Deze gegenereerde ValidateProperty aanroep valideert vervolgens de eigenschap en werkt de status van het ObservableValidator object bij, zodat ui-onderdelen erop kunnen reageren en eventuele validatiefouten correct kunnen weergeven.
Note
Standaard worden alleen veldkenmerken die overnemen van ValidationAttribute , doorgestuurd naar de gegenereerde eigenschap. Dit wordt specifiek gedaan ter ondersteuning van scenario's voor gegevensvalidatie. Alle andere veldkenmerken worden genegeerd, dus het is momenteel niet mogelijk om extra aangepaste kenmerken toe te voegen aan een veld en deze ook toe te passen op de gegenereerde eigenschap. Als dat vereist is (bijvoorbeeld om serialisatie te beheren), kunt u in plaats daarvan een traditionele handmatige eigenschap gebruiken.
Meldingsberichten verzenden
Als de eigenschap is gedeclareerd in een type van waaruit wordt ObservableRecipientovergenomen, kunt u het NotifyPropertyChangedRecipients kenmerk gebruiken om de generator te instrueren ook code in te voegen om een gewijzigd bericht voor de eigenschapswijziging te verzenden. Hierdoor kunnen geregistreerde ontvangers dynamisch reageren op de wijziging. Dat wil gezegd, houd rekening met deze code:
[ObservableProperty]
[NotifyPropertyChangedRecipients]
private string? name;
Dit leidt ertoe dat de volgende eigenschap wordt gegenereerd:
public string? Name
{
get => name;
set
{
string? oldValue = name;
if (SetProperty(ref name, value))
{
Broadcast(oldValue, value);
}
}
}
Met deze gegenereerde Broadcast aanroep wordt vervolgens een nieuwe PropertyChangedMessage<T> aanroep verzonden met behulp van het IMessenger exemplaar dat in het huidige viewmodel wordt gebruikt, naar alle geregistreerde abonnees.
Aangepaste kenmerken toevoegen
In sommige gevallen kan het handig zijn om ook enkele aangepaste kenmerken te hebben voor de gegenereerde eigenschappen. Hiervoor kunt u eenvoudig het [property: ] doel in kenmerklijsten gebruiken boven geannoteerde velden en de MVVM Toolkit stuurt deze kenmerken automatisch door naar de gegenereerde eigenschappen.
Denk bijvoorbeeld aan een veld dat er als volgt uitziet:
[ObservableProperty]
[property: JsonRequired]
[property: JsonPropertyName("name")]
private string? username;
Hiermee wordt een Username eigenschap gegenereerd, met deze twee [JsonRequired] en [JsonPropertyName("name")] kenmerken erboven. U kunt zoveel kenmerklijsten gebruiken die op de eigenschap zijn gericht als u wilt, en alle lijsten worden doorgestuurd naar de gegenereerde eigenschappen.
Examples
- Bekijk de voorbeeld-app (voor meerdere UI-frameworks) om de MVVM Toolkit in actie te zien.
- U vindt ook meer voorbeelden in de eenheidstests.