.NET Fiddle

CSharp · Console

/Program.cs

using System;
using System.ComponentModel;
using System.Threading.Tasks;
					
public class Program
{
	public static async Task Main()
	{
		var foo = new Foo();
		foo.Bar = "Init Value";
		foo.CancelPropertyChanging += Foo_CancelPropertyChanging;

		foo.Bar = "Hello World";
		foo.Bar = "Hello World 2";
		Console.WriteLine(foo.Bar);
		Console.WriteLine(foo.Bar == "Hello World 2" ? "Error" : "Correct");

		var fooAsync = new Foo();
		fooAsync.Bar = "Init Value";
		fooAsync.CancelPropertyChanging += Foo_AsyncCancelPropertyChanging;

		fooAsync.Bar = "Hello World";
		fooAsync.Bar = "Hello World 2";
		Console.WriteLine(fooAsync.Bar);
		Console.WriteLine(fooAsync.Bar == "Hello World 2" ? "Error" : "Correct");

		//wait for the Async event handlers to fire
		await Task.Delay(3_000);
		
		void Foo_CancelPropertyChanging(object? sender, CancelPropertyChangingEventArgs e)
		{
			Console.WriteLine($"Changing Sync - OldValue: {e.OldValue} | NewValue: {e.NewValue}");

			if (Convert.ToString(e.NewValue) == "Hello World 2")
				e.Cancel = e.Cancel || true;
		}
		async void Foo_AsyncCancelPropertyChanging(object? sender, CancelPropertyChangingEventArgs e)
		{
			await Task.Delay(1_000);
			Console.WriteLine($"Changing Async - OldValue: {e.OldValue} | NewValue: {e.NewValue}");

			if (Convert.ToString(e.NewValue) == "Hello World 2")
				e.Cancel = e.Cancel || true;
		}
	}
}

public class Foo
{
    private string? _bar;
    public event EventHandler<CancelPropertyChangingEventArgs>? CancelPropertyChanging;
    public string? Bar
    {
        get => _bar;
        set
        {
            if (CancelPropertyChanging is { } cancelPropertyChanging)
            {
                var eventArgs = new CancelPropertyChangingEventArgs()
                {
                    Cancel = false,
                    NewValue = value,
                    OldValue = _bar,
                    PropertyName = nameof(Bar),
                };
                cancelPropertyChanging(this, eventArgs);
                if (eventArgs.Cancel)
                    return;
            }

            _bar = value;
        }
    }

    public override string ToString() => Bar ?? "";
}

public class CancelPropertyChangingEventArgs : CancelEventArgs
{
    public object? OldValue { get; set; }
    public object? NewValue { get; set; }
    public string PropertyName { get; set; } = "";
}
;