prism使用复合式命令时,因为自实现的composite command 相当于第三方,存放了vm里command的引用,如果不能使用UnregisterCommand方法回收命令可能会导致内存泄漏。请考虑以下几种情况
1.当所有内容都在同一视图模型
正如官方文档说的那样,某一个view有多个部分(保存逻辑相互独立成单独的command),有个保存按钮可以同时保存所有的内容。这个时候手动UnregisterCommand不会有任何问题,因为都在同一个vm中。
2.打开一个对话框,对话框有几个视图可以相互导航且是单独的viewmodel,各自有着自己保存逻辑。对话框vm有一个全局命令保存所有内容。
因为我们的vm依赖注入常常是瞬态的,如果我打开对话框再去关闭,再打开,你会发现command被注册了多次。这时候需要显示在我们接口增加回收的方法,在对话框关闭时显示解绑绑定。
一个简单的注册视图模型,绑定了登录命令
public UserRegisterViewModel(IRegionManager regionManager, ISettingsCommand settingsCommand,IEventAggregator aggregator)
{
_regionManager = regionManager;
_aggregator = aggregator;
LoginCommand = new DelegateCommand(Login);
GoBackCommand = new DelegateCommand(() =>
{
if (_navigationJournal.CanGoBack)
{
_navigationJournal.GoBack();
}
});
settingsCommand.SaveCommand.RegisterCommand(LoginCommand);
}
登录视图模型绑定了注册命令
public UserLoginViewModel(IRegionManager regionManager,ISettingsCommand settingsCommand)
{
_regionManager = regionManager;
_settingsCommand = settingsCommand;
RegisterCommand = new DelegateCommand(Register).ObservesCanExecute(()=>IsEnabled);
settingsCommand.SaveCommand.RegisterCommand(RegisterCommand);
}
CompositeCommand
public interface ISettingsCommand
{
CompositeCommand SaveCommand { get; }
void UnRegisterSaveCommand();
void UnRegisterAllCommand();
}
public class SettingsCommand:ISettingsCommand
{
public CompositeCommand SaveCommand { get; } = new CompositeCommand(true);
public void UnRegisterSaveCommand()
{
SaveCommand.RegisteredCommands.ToList().ForEach(x=> SaveCommand.UnregisterCommand(x));
}
public void UnRegisterAllCommand()
{
UnRegisterSaveCommand();
}
}
在对话框视图模型关闭时解绑绑定
public class SettingDialogViewModel : BindableBase, IAppDialogAware
{
private readonly IRegionManager _regionManager;
private ISettingsCommand _settingsCommand;
public event Action<IDialogResult> RequestClose;
public ISettingsCommand SettingsCommand
{
get => _settingsCommand;
set => SetProperty(ref _settingsCommand,value);
}
public SettingDialogViewModel(IRegionManager regionManager, ISettingsCommand settingsCommand)
{
_regionManager = regionManager;
SettingsCommand = settingsCommand;
}
public bool CanCloseDialog()
{
return true;
}
public void OnDialogClosed()
{
_settingsCommand.UnRegisterSaveCommand();
DialogParameters parameters = new DialogParameters { { "LoginResult", true } };
RequestClose?.Invoke(new DialogResult(ButtonResult.OK, parameters));
}
public void OnDialogOpened(IDialogParameters parameters)
{
}