2016-05-05 3 views
0

Главного окна:Действия в RelayCommand не работает

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

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. Вы также можете сохранить два параметра в другом месте. Суть в том, что вам нужно сохранить сильную ссылку где-то, кроме 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» выглядит уродливо для меня, и я пытался переместить его в Service logic. Можно ли уйти без вызова 'RaiseCanExecuteChanged'? – Pablo

+1

При каждом изменении условий вам нужно вызвать 'RaiseCanExecuteChanged'. Не обойти это. Что бы я сделал, это сделать свойство 'inProgress' и вызвать' ButtonCommandNew.RaiseCanExecuteChanged(); 'из установщика. Затем вы можете изменить 'inProgress' откуда угодно, и пользовательский интерфейс будет обновлен. – FUR10N

 Смежные вопросы

  • Нет связанных вопросов^_^