RelayCommand中的操作未运行

时间:2016-05-05 18:23:33

标签: c# wpf windows async-await mvvm-light

主窗口:

<Window x:Class="Generator.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:ignore="http://www.galasoft.ch/ignore"
    mc:Ignorable="d ignore"
    Height="309.851"
    Width="673.433"
    Title="Generator"
    DataContext="{Binding Main, Source={StaticResource Locator}}">

    <Grid x:Name="LayoutRoot">
        <Frame x:Name="MainFrame" Content="" NavigationUIVisibility="Hidden" HorizontalAlignment="Left" Height="235" Margin="0,36,0,0" VerticalAlignment="Top" Width="294" Source="/Generator;component/Pages/TCPage.xaml"/>
    </Grid>
</Window>

这是框架内的页面

<Page x:Class="Generator.Pages.TCPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:local="clr-namespace:Generator.Pages"
    mc:Ignorable="d" 
    d:DesignHeight="300" d:DesignWidth="300"
    DataContext="{Binding TCPageVM, Source={StaticResource Locator}}"
    Title="TCPage">

    <Grid>
        <Button x:Name="button" Content="Jobby" HorizontalAlignment="Left" Margin="160,185,0,0" VerticalAlignment="Top" Width="75"
            Command="{Binding ButtonCommandNew}" />
    </Grid>
</Page>

这是页面ModelView中的按钮命令(TCPageVM):

    private bool _inProgress = false;
    private RelayCommand _buttonCommandNew;
    public RelayCommand ButtonCommandNew
    {
        get
        {
            var worker = new TCService();

            return _buttonCommandNew
                   ?? (_buttonCommandNew = new RelayCommand(async () =>
                   {
                       var progress = new Progress<string>(status =>
                       {
                           ProgressText = status;
                       });

                       _inProgress = true;
                       _buttonCommandNew.RaiseCanExecuteChanged();

                       await worker.GenerateConfiguration(1, "", "", progress);

                       _inProgress = false;
                       _buttonCommandNew.RaiseCanExecuteChanged();

                   }, () => !_inProgress

                ));
        }
    }

这是服务实施:

public Task<bool> GenerateConfiguration(int cellCount, string templateFilePath, string outputFilePath, IProgress<string> progress)
{
    return Task.Run(() => RunConfigurator(progress));
}

private bool RunConfigurator(IProgress<string> progress)
{
    Thread.Sleep(6000);
    progress.Report("Yeah!");
    return true;
}

问题是按钮已启用,但操作未运行。

1 个答案:

答案 0 :(得分:2)

RelayCommand并未强烈引用您传递给它的操作。它只是一个弱的参考。创建RelayCommand后,该命令是唯一一个引用您提供的操作的命令。由于它是一个弱引用,因此可用于垃圾收集。正确反映启用状态的原因是,在开始时评估它可能没有被垃圾收集。

您可以通过将操作设置为类的命名方法来修复它,然后将该方法传递给RelayCommand。您还可以将这两个参数存储在其他位置。最重要的是,您需要在RelayCommand以外的地方保留强引用。

public RelayCommand ButtonCommandNew
{
    get
    {
        return _buttonCommandNew
               ?? (_buttonCommandNew = new RelayCommand(ExecuteAction, CanExecuteAction));
    }
}

private async void ExecuteAction()
{
    var worker = new TCService();
    var progress = new Progress<string>(status =>
    {
        ProgressText = status;
    });

    _inProgress = true;
    _buttonCommandNew.RaiseCanExecuteChanged();

    await worker.GenerateConfiguration(1, "", "", progress);

    _inProgress = false;
    _buttonCommandNew.RaiseCanExecuteChanged();
}

private bool CanExecuteAction() 
{
    return !_inProgress;
}