Search code examples
c#wpfrx.netreactive-property

Zip does not behave as expected


In my latest project I decided to test out some features the world of reactive programming offers. Since it is a C# project I've started to use the System.Reactive and the ReactiveProperty nuget packages. In my project I tried to combine 2 properties that are bound to WPF textbox controls by the following code:

    public ReactiveProperty<string> InputFieldFirst { get; set; }
    public ReactiveProperty<string> InputFieldSecond { get; set; }
    public ReactiveProperty<string> RxTest { get; set; }

    public MainViewModel()
    {

        InputFieldFirst = new ReactiveProperty<string>("Demo");
        InputFieldSecond = new ReactiveProperty<string>("Test");
        RxTest = InputFieldFirst.Zip(InputFieldSecond, CombineStrings).Delay(TimeSpan.FromMilliseconds(500)).ToReactiveProperty();

    }

    private string CombineStrings(string a, string b)
    {
        return $"{a} {b}";
    }

The textbox bound to RxTest gets the initial value of "Demo Test" - but when I edit the content of the textboxes that are bound either to InputFieldFirst or InputFieldSecond then no update is triggered.

When I change the code as follows, then all updates to InputFieldFirst are visible, delayed in RxTest as expected.

    public MainViewModel(IReactiveRepository<DemoContent> repo)
    {
        InputFieldFirst = new ReactiveProperty<string>("Demo");
        InputFieldSecond = new ReactiveProperty<string>("Test");
        RxTest = InputFieldFirst.Delay(TimeSpan.FromMilliseconds(500)).ToReactiveProperty();
    }

Any hint how to setup the .Zip() would be very nice.

Update for completion

XAML Code for the textboxes

    <Grid>
        <StackPanel>
            <TextBox Text="{Binding InputFieldFirst.Value, UpdateSourceTrigger=PropertyChanged}"></TextBox>
            <TextBox Text="{Binding InputFieldSecond.Value, UpdateSourceTrigger=PropertyChanged}"></TextBox>
            <TextBox Text="{Binding RxTest.Value}"></TextBox>
        </StackPanel>
    </Grid>

Solution

  • I think you want to use CombineLatest instead of Zip. Zip works like a zipper: Match up the nth message of Stream1 with the nth message of Stream2.

    Example:

    Stream1: A----B-----C----D--E-
    Stream2: 1-2-3----4---5-6--7--
    Zip    : A1---B2----C3---D4-E5
    

    Doesn't matter that the numbers come out faster: Zip always matches the 1st number with 1st letter, 2nd number with 2nd letter, etc..