Reputation: 29529
The main window:
<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>
This is the page inside frame
<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>
This is the button command in ModelView of the 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
));
}
}
This is service implementation:
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;
}
The problem is that the button is enabled, but the action is not running.
Upvotes: 0
Views: 158
Reputation: 760
RelayCommand
doesn't keep a strong reference to the action that you are passing to it. It only keeps a weak reference. After you create the RelayCommand
, that command is the only one that has a reference to the action you give it. Since it's a weak reference, it is available for garbage collection. The reason the enabled status is reflected correctly is that it probably hasn't been garbage collected when that is evaluated at the beginning.
You can fix it by making the action a named method on the class, and then pass that method to the RelayCommand
. You could also store the two parameters somewhere else. Bottom line is that you need to keep a strong reference somewhere other than 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;
}
Upvotes: 2