Prism DelegateCommand 的 CanExecute 在 RaiseCanExecuteChanged 后获取空参数
Prism DelegateCommand's CanExecute getting null parameter after RaiseCanExecuteChanged
我正在尝试编写一个 ListView
,其中每个项目都有一个绑定到 DelegateCommand
的按钮。我希望此命令的 CanExecute
基于项目的布尔值 属性。 ItemSource
是一个 ObservableCollection
,我使用 async
方法填充它。问题是,当 RaiseCanExecuteChanged()
被触发时,CanExecute
接收 null
作为 parameter.After,当我使用另一个 UI 绑定命令到 RaiseCanExecuteChanged()
时,该方法运行正常。
这是视图的一部分:
<ListView x:Name="root" ItemsSource="{Binding olVersions}" IsSynchronizedWithCurrentItem="true" HorizontalContentAlignment="Stretch">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=sFullName}" Grid.Column="0" VerticalAlignment="Center"></TextBlock>
<Button Grid.Column="1" Content="Run" CommandParameter="{Binding}" Command="{Binding ElementName=root, Path=DataContext.cRunVersionCommand}"></Button>
<Button Grid.Column="2" Content="Download" CommandParameter="{Binding}" Command="{Binding ElementName=root, Path=DataContext.cDownloadVersionCommand}"></Button>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
这是视图模型:
public class VersionsTabViewModel : BindableBase
{
public ObservableCollection<CVersion> olVersions { get; private set; }
public DelegateCommand<CVersion> cRunVersionCommand { get; private set; }
public DelegateCommand<CVersion> cDownloadVersionCommand { get; private set; }
private IVersionManager c_version_manager;
public VersionsTabViewModel(IVersionManager cVersionManager)
{
olVersions = new ObservableCollection<CVersion>();
cRunVersionCommand = new DelegateCommand<CVersion>(v_try_run_version, b_can_run);
cDownloadVersionCommand = new DelegateCommand<CVersion>(v_try_download_version);
c_version_manager = cVersionManager;
v_read_available_versions();
}
private async void v_read_available_versions()
{
List<CVersion> l_versions = await c_version_manager.lGetVersions();
List<CVersion> l_versions_sorted = l_versions.OrderByDescending(cVersion => cVersion.cSemanticVersion).ToList();
olVersions.Clear();
olVersions.AddRange(l_versions_sorted);
cRunVersionCommand.RaiseCanExecuteChanged();
}
private void v_try_run_version(CVersion cVersionToRun)
{
MessageBox.Show($"Run {cVersionToRun.sFullName}", "Run"); //TODO
}
private void v_try_download_version(CVersion cVersionToDownload)
{
MessageBox.Show($"Download {cVersionToDownload.sFullName}", "Download"); //TODO
cRunVersionCommand.RaiseCanExecuteChanged();
}
private bool b_can_run(CVersion cVersion)
{
return cVersion?.bIsInstalled ?? false;
}
}
这似乎是命令绑定的一般问题,有一个相关的问题,here。为了使其适用于您的情况,您必须将 ElementName
绑定从
更改为 root
Command
属性
Command="{Binding ElementName=root, Path=DataContext.cRunVersionCommand}"
像这样绑定到父 ListView
控件的相对源。
Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListView}}, Path=DataContext.cRunVersionCommand}"
我正在尝试编写一个 ListView
,其中每个项目都有一个绑定到 DelegateCommand
的按钮。我希望此命令的 CanExecute
基于项目的布尔值 属性。 ItemSource
是一个 ObservableCollection
,我使用 async
方法填充它。问题是,当 RaiseCanExecuteChanged()
被触发时,CanExecute
接收 null
作为 parameter.After,当我使用另一个 UI 绑定命令到 RaiseCanExecuteChanged()
时,该方法运行正常。
这是视图的一部分:
<ListView x:Name="root" ItemsSource="{Binding olVersions}" IsSynchronizedWithCurrentItem="true" HorizontalContentAlignment="Stretch">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=sFullName}" Grid.Column="0" VerticalAlignment="Center"></TextBlock>
<Button Grid.Column="1" Content="Run" CommandParameter="{Binding}" Command="{Binding ElementName=root, Path=DataContext.cRunVersionCommand}"></Button>
<Button Grid.Column="2" Content="Download" CommandParameter="{Binding}" Command="{Binding ElementName=root, Path=DataContext.cDownloadVersionCommand}"></Button>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
这是视图模型:
public class VersionsTabViewModel : BindableBase
{
public ObservableCollection<CVersion> olVersions { get; private set; }
public DelegateCommand<CVersion> cRunVersionCommand { get; private set; }
public DelegateCommand<CVersion> cDownloadVersionCommand { get; private set; }
private IVersionManager c_version_manager;
public VersionsTabViewModel(IVersionManager cVersionManager)
{
olVersions = new ObservableCollection<CVersion>();
cRunVersionCommand = new DelegateCommand<CVersion>(v_try_run_version, b_can_run);
cDownloadVersionCommand = new DelegateCommand<CVersion>(v_try_download_version);
c_version_manager = cVersionManager;
v_read_available_versions();
}
private async void v_read_available_versions()
{
List<CVersion> l_versions = await c_version_manager.lGetVersions();
List<CVersion> l_versions_sorted = l_versions.OrderByDescending(cVersion => cVersion.cSemanticVersion).ToList();
olVersions.Clear();
olVersions.AddRange(l_versions_sorted);
cRunVersionCommand.RaiseCanExecuteChanged();
}
private void v_try_run_version(CVersion cVersionToRun)
{
MessageBox.Show($"Run {cVersionToRun.sFullName}", "Run"); //TODO
}
private void v_try_download_version(CVersion cVersionToDownload)
{
MessageBox.Show($"Download {cVersionToDownload.sFullName}", "Download"); //TODO
cRunVersionCommand.RaiseCanExecuteChanged();
}
private bool b_can_run(CVersion cVersion)
{
return cVersion?.bIsInstalled ?? false;
}
}
这似乎是命令绑定的一般问题,有一个相关的问题,here。为了使其适用于您的情况,您必须将 ElementName
绑定从
root
Command
属性
Command="{Binding ElementName=root, Path=DataContext.cRunVersionCommand}"
像这样绑定到父 ListView
控件的相对源。
Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListView}}, Path=DataContext.cRunVersionCommand}"