Add flag to NotifyPropertyChangedFor and NotifyCanExecuteChangedFor that allows notification on sub property changes
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 35/100
- Tipo di issue
- Funzionalità
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Tranquilla
- Stack tecnologico
- csharp
- Ambito
- developer-experience
Direzione di ricerca
Inizia con NotifyPropertyChangedForAttribute e NotifyCanExecuteChangedForAttribute, quindi segui i punti di ingresso dei generatori di codice sorgente di ObservableProperty e RelayCommand. Confronta il setter generato richiesto e il gestore delle sottoproprietà con l'output generato attuale. Il lavoro è completato quando è stata definita un'API e sono disponibili notifiche funzionanti per le modifiche alle sottoproprietà, incluso il caso di RelayCommand.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Overview
I frequently have a property that depends on the sub-property of another property in my viewmodels. The most common case for me is the IsRunning property of AsyncRelayCommand, but I've run into many other examples.
I'd like some sort of way to indicate that another property or command has changed when a sub-property has changed. Ideally this could be extended to [RelayCommand] declarations as well so that when the automatically generated command starts or stops, other properties are notified.
API breakdown
Preferably we could add a boolean property called NotifyOnSubPropertyChanged to NotifyPropertyChangedForAttribute and NotifyCanExecuteChangedForAttribute that opts into this behavior when set to true.
Usage example
I would use it like this:
public partial class TestViewModel : ObservableObject
{
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(FormattedProp1), NotifyOnSubPropertyChanged = true)]
[NotifyCanExecuteChangedFor(nameof(Command1Command), NotifyOnSubPropertyChanged = true)]
public partial SubViewModel SubViewModel { get; private set; } = new();
public string FormattedProp1 => "_" + SubViewModel.Prop1 + "_";
[RelayCommand(CanExecute = nameof(CanDoThing1))]
[property: NotifyCanExecuteChangedFor(nameof(DoThing2Command), NotifyOnSubPropertyChanged = true)]
private Task DoThing1() => Task.CompletedTask;
private bool CanDoThing1() => SubViewModel.Prop1 is not null;
[RelayCommand(CanExecute = nameof(CanDoThing2))]
private void DoThing2() { }
private bool CanDoThing2() => !DoThing1Command.IsRunning;
}
public partial class SubViewModel : ObservableObject
{
[ObservableProperty]
public partial string Prop1 { get; set; }
}
I think the generated code would look something like this for the SubViewModel property:
/// <inheritdoc/>
[global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "8.4.0.0")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public partial global::WpfTests.SubViewModel SubViewModel
{
get => field;
private set
{
if (!global::System.Collections.Generic.EqualityComparer<global::WpfTests.SubViewModel>.Default.Equals(field, value))
{
OnSubViewModelChanging(value);
OnSubViewModelChanging(default, value);
OnPropertyChanging(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangingArgs.SubViewModel);
OnPropertyChanging(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangingArgs.FormattedProp1);
(field as INotifyPropertyChanged)?.PropertyChanged -= OnSubPropertyChanged;
field = value;
(field as INotifyPropertyChanged)?.PropertyChanged += OnSubPropertyChanged;
OnSubViewModelChanged(value);
OnSubViewModelChanged(default, value);
OnPropertyChanged(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangedArgs.SubViewModel);
OnPropertyChanged(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangedArgs.FormattedProp1);
DoThing1Command.NotifyCanExecuteChanged();
}
void OnSubPropertyChanged(object? sender, PropertyChangedEventArgs args)
{
OnPropertyChanged(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangedArgs.FormattedProp1);
DoThing1Command.NotifyCanExecuteChanged();
}
}
Note that the handler for detecting sub-property changes is removed and added in the parent property setter, and the handler itself is a local function of the setter that is populated based on the property names provided.
I'm not sure how it would integrate into the RelayCommandAttribute, but it would be really nice to have for that for asynchronous commands.
Breaking change?
No
Alternatives
Right now all of this has to be configured in the constructor or initializer, and greatly hinders some of the benefits of the source generators.
An alternative might be to have a new attribute, but I think this is a little cleaner.
Additional context
No response
Help us help you
Yes, but only if others can assist
- Lingua principale
- C#
- Stelle
- 3.8k
- Fork
- 401
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di CommunityToolkit/dotnet
-
RelayCommand<T>.CanExecute(null) returns false for value types without a predicateForse già presa @apachezy l’ha presa 78 giorni fa. Apertabug :bug:
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
CommunityToolkit/dotnet#1206 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
CommunityToolkit/dotnet#1186 ·
-
bug :bug:
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 68/100
CommunityToolkit/dotnet#648 ·
-
bug :bug:
Difficoltà 3/5 1-2 giorni Idoneità per principianti 68/100
CommunityToolkit/dotnet#1215 ·
-
Add segmented buffering and sequence reads to `ArrayPoolBufferWriter<T>`Forse già presa @paulomorgado l’ha presa 15 giorni fa. Apertafeature request :mailbox_with_mail:
Difficoltà 5/5 Più di una settimana Idoneità per principianti 45/100
CommunityToolkit/dotnet#1214 ·
Tutte le issue di CommunityToolkit/dotnet
Issue simili
-
A numeric literal is parsed in the host's culture, so 1.5 is 15 in a made EXE on a comma-decimal OSApertabug interpreter silently-wrong small
Difficoltà 2/5 1-3 ore Idoneità per principianti 83/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
reactiveui/ReactiveUI.Binding.SourceGenerators#176 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 76/100
dotnet/csharpstandard#1830 ·
I maintainer di solito rispondono entro 1 giorno
-
c:docs p:high size:S t:docs
Difficoltà 2/5 1-3 ore Idoneità per principianti 64/100
I maintainer di solito rispondono entro 1 giorno