Home > Blockchain >  ReactiveUI nested Command IsExecuting does not change until window closes
ReactiveUI nested Command IsExecuting does not change until window closes

Time:04-30

For demonstration, I have a window MainWindow with a button that open a dialog Dialog when clicked. The dialog has a button Hello. When the Hello button is clicked, a command will execute, which wait 3s and show a MessagaBox with message "Hello, world!". I subscribe to the command's IsExecuting and display it when I get a value. The problem is that after I click the Hello button, only "Hello, world!" is displayed, the IsExecuting value("True" and "False") is not displayed until the dialog(class Dialog) closes.

MainWindow:

<Window x:Class="WpfDemo.MainWindow"
        ...
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <local:MainViewModel x:Key="ViewModel"></local:MainViewModel>
    </Window.Resources>
    <Window.DataContext>
        <StaticResource ResourceKey="ViewModel"></StaticResource>
    </Window.DataContext>
    <Grid>
        <Button Name="ShowDialog" 
                Command="{Binding CommandShowDialog}">Show Dialog</Button>
    </Grid>
</Window>

MainViewModel:

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

    public MainViewModel()
    {
        CommandShowDialog = ReactiveCommand.Create(ShowDialog);
    }

    private void ShowDialog()
    {
        new Dialog().ShowDialog();
    }
}  

Dialog:

<Window x:Class="WpfDemo.Dialog"
        ...
        Title="Dialog" Height="450" Width="800">
    <Window.Resources>
        <local:DialogViewModel x:Key="vm"></local:DialogViewModel>
    </Window.Resources>
    <Window.DataContext>
        <StaticResource ResourceKey="vm"></StaticResource>
    </Window.DataContext>
    <Grid>
        <Button Name="Hello" Command="{Binding Command}">Hello, world!</Button>
    </Grid>
</Window>

DialogViewModel

public class DialogViewModel : ReactiveObject
{
    public ReactiveCommand<Unit, string> Command { get; set; }

    private readonly ObservableAsPropertyHelper<bool> _isExecuting;

    public bool IsExecuting => _isExecuting.Value;

    public DialogViewModel()
    {
        Command = ReactiveCommand.CreateFromTask(Hello);
        _isExecuting = Command.IsExecuting
            .ToProperty(this, x => x.IsExecuting);
        this.WhenAnyValue(x => x.IsExecuting)
            .Subscribe(b => MessageBox.Show(b.ToString()));
    }

    private async Task<string> Hello()
    {
        return await Task.Run(delegate
        {
            Thread.Sleep(3000);
            const string s = "Hello, world!";
            MessageBox.Show(s);
            return s;
        });
    }
}

CodePudding user response:

ShowDialog() blocks the until the dialog is closed. Call Show() instead.

  • Related