TomMaier
TomMaier

Reputation: 151

ReactiveCommand in WPF throws exception with Subscribe

I have a simple demo application with ReactiveUI:

//in the viewmodel
class MainViewModel : ReactiveObject
{
    public ReactiveUI.ReactiveCommand<Unit, Unit> MyReactiveCommand { get; }

    public MainViewModel()
    {
        MyReactiveCommand = ReactiveCommand.Create(() => { MessageBox.Show("Hello"); }, outputScheduler: RxApp.MainThreadScheduler);
    }
}

In the view XAML

<Window.DataContext>
    <local:MainViewModel/>
</Window.DataContext>

<Grid>
    <WrapPanel HorizontalAlignment = "Left">
        <Button Content="button" Command="{Binding MyReactiveCommand}"/>
    </WrapPanel>
</Grid>

When you press the button there should be a Message Box but instead I get the following error:

System.InvalidOperationException: 'The calling thread cannot access this object because a different thread owns it.'

I have tried returning a value and then subscribing like Glenn suggested but that had the same problem. At least with this code the Message Box opens before it crashes ;)

public class MainViewModel : ReactiveObject
{
    public ReactiveCommand<Unit, Unit> MyReactiveCommand { get; }

    public MainViewModel()
    {
        MyReactiveCommand = ReactiveCommand.CreateFromObservable(DoSometing);
        MyReactiveCommand.Subscribe(x => { MessageBox.Show("Hello"); });
    }

    public IObservable<Unit> DoSometing()
    {
        return Observable.Start(() => { });
    }
}

Upvotes: 0

Views: 647

Answers (1)

Glenn Watson
Glenn Watson

Reputation: 2888

So a couple things to be aware of. ReactiveCommand.CreateFromObservable has a parameter called outputScheduler and this will be where the Subscribe's output will go to. You can pass RxApp.MainThreadScheduler here.

public class MainViewModel : ReactiveObject
{
    public ReactiveCommand<Unit, Unit> MyReactiveCommand { get; }

    public MainViewModel()
    {
        MyReactiveCommand = ReactiveCommand.CreateFromObservable(DoSometing, outputScheduler: RxApp.MainThreadScheduler);
        MyReactiveCommand.Subscribe(x => { MessageBox.Show("Hello"); });
    }

    public IObservable<Unit> DoSometing()
    {
        return Observable.Start(() => { });
    }
}

Note also make sure you have installed the NuGet package ReactiveUI.WPF

Upvotes: 1

Related Questions