Search code examples
reactiveuirx.net

How to get ReactiveUI WhenAnyValue to emit when property is changed outside the setter of class


I am wondering how I could still trigger ReactiveUI's WhenAnyValue with a property that could be changed outside of the setter of the property in the class. Please excuse the example just tried to make something quick to get the point across. Lets say I have two classes one being a Person and the other being an Address.

public class Address : ReactiveObject
{
    [Reactive]
    public string Street1 { get; set; }
    [Reactive]
    public string Street2 { get; set; }
    [Reactive]
    public string State { get; set; }
    [Reactive]
    public string City { get; set; }
    [Reactive]
    public string ZipCode { get; set; }
}

public class Person : ReactiveObject
{

    [Reactive]
    public string Name { get; set; }

    [Reactive]
    public Address Address { get; set; }


    public Person(Address address)
    {
        Address = address;
        address.Changed .Subscribe(_ =>
        {
            //Tried this way
            this.RaisePropertyChanged(_.PropertyName);

            //Also tried this way
            this.RaisePropertyChanged(nameof(Address));
        });

        this.Changed.Subscribe(_ =>
        {
            Console.WriteLine($"Person Property: {_.PropertyName} changed");
        });

        this.WhenAnyValue(_ => _.Name, _ => _.Address, (a, b) => "Emit").Subscribe(Console.WriteLine);
    }
}

private static void Main(string[] args)
{
    var address = new Address
    {
        Street1 = "Street1",
        Street2 = "Street2",
        City = "City",
        State = "LA",
        ZipCode = "11111"
    };

    var person = new Person(address);

    person.Name = "Name";
    Task.Delay(3000).Wait();

    address.City = "CityChanged";


    Console.ReadLine();
}

I would think I would only need to Subscribe to the Address Changed Observable and then from within the Person RaisePropertyChanged for the Address Property. It does emit to the Person's Changed Observable and that behaves as I would expect but the WhenAnyValue Observable within Person never emits in that scenario.


Solution

  • I figured out the issue. The problem is I have to add all nested properties to the WhenAnyValue. In my example if i change this line

    this.WhenAnyValue(_ => _.Name, _ => _.Address, (a, b) => "Emit").Subscribe(Console.WriteLine);
    

    to

    this.WhenAnyValue(_ => _.Name, _ => _.Address.City, (a, b) => "Emit").Subscribe(Console.WriteLine);
    

    It emits. The key there is changing it from _.Address to _.Address.City. Furthermore it still emits without needing to Subscribe to the Address.Changed Observable which is even better.