2016-05-05 2 views
0

メインウィンドウを実行していない:アクション

<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> 

これは、ページ(TCPageVM)ののModelViewでボタンコマンドです:

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; 
} 

問題はボタンが有効になっているが、アクションが実行されていないことです。

答えて

2

RelayCommandあなたが渡すアクションを強く参照することはありません。それは弱い参照のみを保持します。 RelayCommandを作成した後、そのコマンドに与えられたアクションへの参照を持つ唯一のコマンドです。それは弱い参照であるため、ガベージコレクションのために利用できます。有効なステータスが正しく反映されるのは、最初に評価されたときにガベージコレクションが行われていない可能性があるためです。

アクションをクラスに名前付きメソッドを作成して修正し、そのメソッドをRelayCommandに渡すことができます。 2つのパラメータを別の場所に格納することもできます。要するに、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; 
} 
+0

完璧な答え。ただ一つの最後の質問 - あなたがボタンを有効/無効にする方法が唯一の方法だと思いますか? RaiseCanExecuteChangedが私には醜いと思われ、サービスロジックに移そうとしていました。 'RaiseCanExecuteChanged'を呼び出さずに立ち去ることは可能ですか? – Pablo

+1

条件が変わるたびに 'RaiseCanExecuteChanged'を呼び出す必要があります。それを回避することはできません。私が行うことは、 'inProgress'をプロパティにし、Setterから' ButtonCommandNew.RaiseCanExecuteChanged(); 'を呼び出すことです。そして、どこからでも 'inProgress'を変更することができ、UIが更新されます。 – FUR10N