我真的用这个挠我的脑袋。我有一个打开对话框的主窗口。对话框关闭后,对话框中绑定命令的CanExecute方法仍在执行。这在我的应用程序中造成了一些严重的问题。ui何时从命令中分离?
示例:
MainWindow具有带点击处理程序的按钮。这是Click事件处理程序:
private void Button_Click(object sender, RoutedEventArgs e)
{
DialogWindow window = new DialogWindow();
window.ShowDialog();
}
在我绑定的物品控制在对话窗口中的静态资源的对话框,并在列表中的每个项目都有一个命令:
<Window.Resources>
<Collections:ArrayList x:Key="itemsSource">
<local:ItemViewModel Description="A"></local:ItemViewModel>
<local:ItemViewModel Description="B"></local:ItemViewModel>
<local:ItemViewModel Description="C"></local:ItemViewModel>
</Collections:ArrayList>
<DataTemplate DataType="{x:Type local:ItemViewModel}">
<Button Grid.Column="1" Command="{Binding Path=CommandClickMe}" Content="{Binding Path=Description}" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">
</Button>
</DataTemplate>
</Window.Resources>
<Grid>
<ToolBar ItemsSource="{StaticResource itemsSource}"></ToolBar>
</Grid>
这是该视图模型:
public class ItemViewModel
{
private RelayWpfCommand<object> _commandClickMe;
public RelayWpfCommand<object> CommandClickMe
{
get
{
if (_commandClickMe == null)
_commandClickMe = new RelayWpfCommand<object>(obj => System.Console.Out.WriteLine("Hei mom"), obj => CanClickMe());
return _commandClickMe;
}
}
private bool CanClickMe()
{
return true;
}
public string Description { get; set; }
这是DelegateCommand实现:
public class RelayWpfCommand<T> : ICommand
{
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
private readonly Predicate<T> _canExecute;
private readonly Action<T> _execute;
public RelayWpfCommand(Action<T> execute, Predicate<T> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
/// <summary>
/// Forces a notification that the CanExecute state has changed
/// </summary>
public void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
}
public bool CanExecute(T parameter)
{
return _canExecute(parameter);
}
public void Execute(T parameter)
{
_execute(parameter);
}
bool ICommand.CanExecute(object parameter)
{
if (!IsParameterValidType(parameter))
return false;
return CanExecute((T)parameter);
}
void ICommand.Execute(object parameter)
{
if (!IsParameterValidType(parameter))
throw new ArgumentException(string.Format("Parameter must be of type {0}", typeof(T)));
Execute((T)parameter);
}
private static bool IsParameterValidType(object parameter)
{
if (parameter != null && !typeof(T).IsAssignableFrom(parameter.GetType()))
return false;
return true;
}
}
现在,如果关闭对话框窗口并在ViewModel的CanExecute(我使用Prism DelegateCommand与弱事件订阅)方法中设置断点,我注意到它会触发,尽管对话框已关闭。为什么对话框中的按钮与ViewModel上的命令之间的绑定仍然存在?
我正在通过关闭窗口并在稍后在viewmodel的“CanClickMe”方法中设置一个断点来检查它是否正在执行。它会被执行一段时间,然后突然停止(可能是由于GC)。这种非恶意行为正在引发问题,因为在实际应用中,视角模型可能已经被处置。
在什么时候你看到这个?窗口实例在关闭后仍处于范围内,直到您离开Click事件。这是为了允许调用者访问窗口中的属性(例如,考虑一个选项窗口)。另外,CanExecute中的内容会导致问题?问题实际上是你在CanExecute中创建副作用吗? – 2010-11-04 12:46:28
查看我的评论 – Marius 2010-11-04 13:09:20