Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Typen ObservableProperty är ett attribut som gör det möjligt att generera observerbara egenskaper från kommenterade fält. Syftet är att avsevärt minska mängden standardkod som behövs för att definiera observerbara egenskaper.
Note
För att fungera måste kommenterade fält vara i en partiell klass med nödvändig INotifyPropertyChanged infrastruktur. Om typen är kapslad måste alla typer i deklarationssyntaxträdet också kommenteras som partiella. Om du inte gör det uppstår kompileringsfel eftersom generatorn inte kan generera en annan partiell deklaration av den typen med den begärda observerbara egenskapen.
Plattforms-API:er:
ObservableProperty,NotifyPropertyChangedFor,NotifyCanExecuteChangedFor,NotifyDataErrorInfo,NotifyPropertyChangedRecipients,ICommand,IRelayCommand, ObservableValidator,PropertyChangedMessage<T>,IMessenger
Så här fungerar det
Attributet ObservableProperty kan användas för att kommentera ett fält i en partiell typ, så här:
[ObservableProperty]
private string? name;
Och den genererar en observerbar egenskap som den här:
public string? Name
{
get => name;
set => SetProperty(ref name, value);
}
Det kommer också att göra det med en optimerad implementering, så slutresultatet blir ännu snabbare.
Note
Namnet på den genererade egenskapen skapas baserat på fältnamnet. Generatorn förutsätter att fältet heter antingen lowerCamel, _lowerCamel eller m_lowerCamel, och att det omvandlas till UpperCamel för att följa rätt namngivningskonventioner för .NET. Den resulterande egenskapen har alltid offentliga åtkomstorer, men fältet kan deklareras med valfri synlighet (private rekommenderas).
Köra kod vid ändringar
Den genererade koden är faktiskt lite mer komplex än så, och anledningen till det är att den även exponerar vissa metoder som du kan implementera för att ansluta till meddelandelogiken och köra ytterligare logik när egenskapen håller på att uppdateras och direkt efter att den har uppdaterats, om det behövs. Den genererade koden liknar det här:
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);
På så sätt kan du implementera någon av dessa metoder för att mata in ytterligare kod. De två första är användbara när du vill köra viss logik som bara behöver referera till det nya värdet som egenskapen har angetts till. De andra två är användbara när du har lite mer komplex logik som också måste uppdatera vissa tillstånd för både det gamla och nya värdet som anges.
Här är till exempel ett exempel på hur de två första överlagrade versionerna kan användas:
[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}");
}
Och här är ett exempel på hur de andra två överlagringarna kan användas:
[ObservableProperty]
private ChildViewModel? selectedItem;
partial void OnSelectedItemChanging(ChildViewModel? oldValue, ChildViewModel? newValue)
{
if (oldValue is not null)
{
oldValue.IsSelected = true;
}
if (newValue is not null)
{
newValue.IsSelected = true;
}
}
Du kan bara implementera ett antal metoder bland de som är tillgängliga, eller ingen av dem. Om de inte implementeras (eller om bara ett av dem implementeras) kommer hela anropet/anropen helt enkelt att tas bort av kompilatorn, så det medför ingen prestandapåverkan alls i de fall där den här extra funktionaliteten inte krävs.
Note
De genererade metoderna är partiella metoder utan implementering, vilket innebär att om du väljer att implementera dem kan du inte ange en explicit tillgänglighet för dem. Det vill: implementeringar av dessa metoder bör också deklareras som bara partial metoder, och de kommer alltid implicit att ha privat tillgänglighet. Om du försöker lägga till en explicit tillgänglighet (t.ex. att lägga till public eller private) uppstår ett fel, eftersom det inte är tillåtet i C#.
Meddela beroende egenskaper
Anta att du har en FullName egenskap som du vill skapa ett meddelande för när ändringar Name sker. Du kan göra det med hjälp av attributet NotifyPropertyChangedFor så här:
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(FullName))]
private string? name;
Detta resulterar i en genererad egenskap som motsvarar följande:
public string? Name
{
get => name;
set
{
if (SetProperty(ref name, value))
{
OnPropertyChanged("FullName");
}
}
}
Meddela beroende kommandon
Anta att du har ett kommando vars körstatus var beroende av värdet på den här egenskapen. Det vill säga att varje gång egenskapen ändras bör kommandots körningstillstånd ogiltigförklaras och beräknas på nytt. Med andra ord, bör ICommand.CanExecuteChanged höjas igen. Du kan uppnå detta med hjälp av attributet NotifyCanExecuteChangedFor :
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(MyCommand))]
private string? name;
Detta resulterar i en genererad egenskap som motsvarar följande:
public string? Name
{
get => name;
set
{
if (SetProperty(ref name, value))
{
MyCommand.NotifyCanExecuteChanged();
}
}
}
För att detta ska fungera måste målkommandot vara en egenskap IRelayCommand .
Begära egenskapsverifiering
Om egenskapen deklareras i en typ som ärver från ObservableValidator är det också möjligt att kommentera den med valideringsattribut och sedan begära att den genererade settern utlöser valideringen för den egenskapen. Detta kan uppnås med attributet NotifyDataErrorInfo :
[ObservableProperty]
[NotifyDataErrorInfo]
[Required]
[MinLength(2)] // Any other validation attributes too...
private string? name;
Detta resulterar i att följande egenskap genereras:
public string? Name
{
get => name;
set
{
if (SetProperty(ref name, value))
{
ValidateProperty(value, "Value2");
}
}
}
Det genererade ValidateProperty anropet verifierar sedan egenskapen och uppdaterar objektets ObservableValidator tillstånd, så att gränssnittskomponenter kan reagera på den och visa eventuella valideringsfel på rätt sätt.
Note
Avsiktligt vidarebefordras endast fältattribut som ärver från ValidationAttribute till den genererade egenskapen. Detta görs specifikt för att stödja dataverifieringsscenarier. Alla andra fältattribut ignoreras, så det är för närvarande inte möjligt att lägga till ytterligare anpassade attribut i ett fält och låta dem även tillämpas på den genererade egenskapen. Om det krävs (t.ex. för att kontrollera serialisering) bör du överväga att använda en traditionell manuell egenskap i stället.
Skicka meddelanden
Om egenskapen deklareras i en typ som ärver från ObservableRecipientkan du använda NotifyPropertyChangedRecipients attributet för att instruera generatorn att även infoga kod för att skicka ett egenskapsändringsmeddelande för egenskapsändringen. Detta gör att registrerade mottagare kan reagera dynamiskt på ändringen. Det vill säga, betrakta följande kod:
[ObservableProperty]
[NotifyPropertyChangedRecipients]
private string? name;
Detta resulterar i att följande egenskap genereras:
public string? Name
{
get => name;
set
{
string? oldValue = name;
if (SetProperty(ref name, value))
{
Broadcast(oldValue, value);
}
}
}
Det genererade anropet till Broadcast kommer sedan att skicka en ny PropertyChangedMessage<T> med den IMessenger-instans som används i den aktuella viewmodellen till alla registrerade prenumeranter.
Lägga till anpassade attribut
I vissa fall kan det vara användbart att även ha vissa anpassade attribut över de genererade egenskaperna. För att uppnå detta kan du helt enkelt använda [property: ] målet i attributlistor över kommenterade fält, och MVVM Toolkit vidarebefordrar automatiskt dessa attribut till de genererade egenskaperna.
Överväg till exempel ett fält som det här:
[ObservableProperty]
[property: JsonRequired]
[property: JsonPropertyName("name")]
private string? username;
Detta genererar en Username egenskap, med dessa två [JsonRequired] och [JsonPropertyName("name")] attribut över den. Du kan använda så många attributlistor som är riktade till egenskapen som du vill, och alla vidarebefordras till de genererade egenskaperna.
Exempel
- Kolla in exempelappen (för flera gränssnittsramverk) för att se MVVM Toolkit i praktiken.
- Du kan också hitta fler exempel i enhetstesterna.
MVVM Toolkit