如果使用嵌套属性而不是普通属性,我很难理解为什么 ICommand.CanExecutes 总是包含以前的值而不是新值。
问题在下面描述,除了使用某种形式的“外观”模式之外,我真的无法找到解决此问题的方法,我在视图模型中创建属性并将它们挂钩到模型中的相应属性。
或者使用该死的 CommandManager.RequerySuggested 事件。这不是最佳的原因是因为视图显示了 30 多个命令,仅计算菜单,如果每次更改时所有 CanExecute 都更新,则所有菜单项/按钮都需要几秒钟才能更新。即使使用下面的示例,仅使用一个命令和按钮以及命令管理器,按钮也需要大约 500 毫秒来启用/禁用自身。
我能想到的唯一原因是在 CanExecute 被触发之前 CommandParameter 绑定没有更新,然后我想你无能为力。
提前致谢 :!
例如
假设我们有这个基本的视图模型
public class BasicViewModel : INotifyPropertyChanged
{
private string name;
public string Name
{
get { return name; }
set {
this.name = value;
RaisePropertyChanged("Name");
Command.RaiseCanExecuteChanged();
}
}
private Project project;
public Project Project
{
get { return project; }
set {
if (project != null) project.PropertyChanged -= ChildPropertyChanged;
if (value != null) value.PropertyChanged += ChildPropertyChanged;
project = value;
RaisePropertyChanged("Project");
}
}
private void ChildPropertyChanged(object sender, PropertyChangedEventArgs e) {
Command.RaiseCanExecuteChanged();
}
public DelegateCommand<string> Command { get; set; }
public BasicViewModel()
{
this.Project = new Example.Project();
Command = new DelegateCommand<string>(this.Execute, this.CanExecute);
}
private bool CanExecute(string arg) {
return !string.IsNullOrWhiteSpace(arg);
}
private void Execute(string obj) { }
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName = null) {
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
和这个模型
public class Project : INotifyPropertyChanged
{
private string text;
public string Text
{
get { return text; }
set
{
text = value;
RaisePropertyChanged("Text");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName = null)
{
var handler = this.PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
现在在我看来,我有这个文本框和按钮。
<Button Content="Button" CommandParameter="{Binding Path=Project.Text}" Command="{Binding Path=Command}" />
<TextBox Text="{Binding Path=Project.Text, UpdateSourceTrigger=PropertyChanged}" />
它有效,每次我在文本框中键入内容时都会调用 CanExecute,但参数始终设置为先前的值。假设我在文本框中写了“H”,CanExecute 被触发,参数设置为 NULL。接下来我写“E”,现在文本框包含“HE”,CanExecute 再次触发。这次仅将参数设置为“H”。
出于某种奇怪的原因,该参数始终设置为以前的值,当我检查 Project.Text 时,它设置为“HE”,但参数仍设置为仅“H”。
如果我现在将命令参数更改为
CommandParameter="{Binding Path=Name}"
和 Textbox.Text 到
Text={Binding Path=Name, UpdateSourceTrigger=PropertyChanged}"
一切正常。CanExecute 参数始终包含最新值而不是先前值。