Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

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

オープン
#1,168 コメント 1 件 リアクション 1 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
5/5
見積もり時間
1週間以上
初心者へのやさしさ
35/100
issue の種類
機能追加
明瞭さ
おおむね明確
活発さ
静か
技術スタック
csharp

調査の方向性

NotifyPropertyChangedForAttribute と NotifyCanExecuteChangedForAttribute から始め、次に ObservableProperty と RelayCommand のソースジェネレーターのエントリポイントを追跡します。要求された生成 setter とサブプロパティハンドラーを、現在の生成出力と比較します。完了とは、API が決定され、RelayCommand のケースを含むサブプロパティの変更に対して通知が機能することです。

索引モデルが issue の本文から書いたものです。

説明

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

主要言語
C#
スター
3.8k
フォーク
401
PR マージ指標
30日以内にマージされた PR はありません

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

CommunityToolkit/dotnet のほかの issue

CommunityToolkit/dotnet の issue をすべて見る

似ている issue

C# の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。