Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

Add flag to NotifyPropertyChangedFor and NotifyCanExecuteChangedFor that allows notification on sub property changes

Aperta
#1,168 1 commento 1 reazione 0 assegnatari Vedi su GitHub

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

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

feature request :mailbox_with_mail:
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

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di CommunityToolkit/dotnet

Tutte le issue di CommunityToolkit/dotnet

Issue simili

Altre issue su C#

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.