RelayCommand 中的操作不是 运行
Action in RelayCommand is not running
主要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>
这是框架内的页面
<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;
}
问题是按钮启用了,但是动作不是运行。
RelayCommand
没有保留对您传递给它的操作的强引用。它只保留弱引用。在您创建 RelayCommand
之后,该命令是唯一一个引用您给它的操作的命令。由于它是弱引用,因此可用于垃圾回收。启用状态被正确反映的原因是它可能在开始评估时没有被垃圾收集。
您可以通过在 class 上使操作成为一个命名方法来修复它,然后将该方法传递给 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;
}
主要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>
这是框架内的页面
<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;
}
问题是按钮启用了,但是动作不是运行。
RelayCommand
没有保留对您传递给它的操作的强引用。它只保留弱引用。在您创建 RelayCommand
之后,该命令是唯一一个引用您给它的操作的命令。由于它是弱引用,因此可用于垃圾回收。启用状态被正确反映的原因是它可能在开始评估时没有被垃圾收集。
您可以通过在 class 上使操作成为一个命名方法来修复它,然后将该方法传递给 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;
}