中继命令 CanExecute 仅在视图模型构造函数中调用一次,但在属性更改时不会再次调用
Relay Command CanExecute is only invoked in the viewmodels constuctor once but won't invoke again when Properties are changed
我想做什么:
加载我的视图时,可以看到几个必填字段(标记为红色)的文本框。只要这些文本框未填写,“下一步”按钮就会被禁用,否则会启用:
按钮的XAML:
<Grid Grid.Row="10" Grid.RowSpan="2" Grid.Column="11" Grid.ColumnSpan="2">
<Button ToolTip="Die Pflichtfelder bitte ausfüllen!" Content="WEITER ZU GRUNDLAGEN" Command="{Binding AngebotKopieren}" Grid.ColumnSpan="2"></Button>
</Grid>
我试过的:
在 Internet 上,我阅读了有关 RelayCommand 的信息,因此决定将其添加到我的项目中以实现上述目标。
在 Viewmodel 的构造函数中,我像这样包含它:
public MyViewModel()
{
AngebotKopieren = new RelayCommand(CopyTemplate, CanCopyTemplate);
}
private ICommand _angebotKopieren;
public ICommand AngebotKopieren
{
get { return _angebotKopieren; }
set { _angebotKopieren = value; OnPropertyChanged("AngebotKopieren"); }
}
如您所见,我使用了两个方法 CopyTemplate() 和 CanCopyTemplate() 。现在,第一个做什么并不重要,但后者应该 return 在所有必填字段都已填写时为真,否则为假。对于这个例子,为了简单起见,我只使用了一个必填字段:
private bool CanCopyTemplate(object obj)
{
if(//(String.IsNullOrEmpty(Nachname) && String.IsNullOrEmpty(Vorname) && String.IsNullOrEmpty(Angebotstitel) &&
String.IsNullOrEmpty(SelAnrede) //&& String.IsNullOrEmpty(StrasseWohnort) && String.IsNullOrEmpty(PLZ_Wohnort)
//&& String.IsNullOrEmpty(Wohnort)))
)
{
return false;
}
return true;
}
但是,当我填写 SelAnrede(绑定到 Combobox Selected Item 属性 with Update Source Trigger=On 属性 的字符串已更改时,该按钮仍处于禁用状态。
我错过了什么?为什么在视图中更改 SelItem 属性 时未调用 CanExecuteChanged() 方法?为什么 CanCopyTemplate() 方法不再被调用?
这里是 RelayCommand-Class 以获得更好的概述:
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#region Konstruktoren
/// <summary>
/// Erzeugt ein neues Command, das immer ausführen kann.
/// </summary>
/// <param name="execute">Die Ausführungslogik...</param>
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
/// <summary>
/// Erzeugt ein neues Command
/// </summary>
/// <param name="execute">Die Ausführungslogik...</param>
/// <param name="canExecute">Die Logik zum Ausführungsstatus...</param>
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion // Konstruktoren
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameters)
{
return _canExecute == null ? true : _canExecute(parameters);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
event EventHandler ICommand.CanExecuteChanged
{
add
{
//throw new NotImplementedException();
}
remove
{
//throw new NotImplementedException();
}
}
public void Execute(object parameters)
{
_execute(parameters);
}
#endregion // ICommand Members
}
每当设置了在命令的 CanCopyTemplate
方法中检查其值的 属性 时,您应该调用引发其 CanExecuteChanged
事件的命令的方法。
因此,例如,SelAnrede
属性 的 setter 应该像这样实现:
private string _selAnrede;
public string SelAnrede
{
get { return _selAnrede; }
set
{
_selAnrede = value;
OnPropertyChanged(nameof(SelAnrede));
CommandManager.InvalidateRequerySuggested();
}
}
CanExecuteChanged
事件不是“自动”引发的事件,但大多数 ICommand
的实现都有一个为您引发它的方法。你只需要确定你真的调用了它。
我想做什么:
加载我的视图时,可以看到几个必填字段(标记为红色)的文本框。只要这些文本框未填写,“下一步”按钮就会被禁用,否则会启用:
按钮的XAML:
<Grid Grid.Row="10" Grid.RowSpan="2" Grid.Column="11" Grid.ColumnSpan="2">
<Button ToolTip="Die Pflichtfelder bitte ausfüllen!" Content="WEITER ZU GRUNDLAGEN" Command="{Binding AngebotKopieren}" Grid.ColumnSpan="2"></Button>
</Grid>
我试过的: 在 Internet 上,我阅读了有关 RelayCommand 的信息,因此决定将其添加到我的项目中以实现上述目标。 在 Viewmodel 的构造函数中,我像这样包含它:
public MyViewModel()
{
AngebotKopieren = new RelayCommand(CopyTemplate, CanCopyTemplate);
}
private ICommand _angebotKopieren;
public ICommand AngebotKopieren
{
get { return _angebotKopieren; }
set { _angebotKopieren = value; OnPropertyChanged("AngebotKopieren"); }
}
如您所见,我使用了两个方法 CopyTemplate() 和 CanCopyTemplate() 。现在,第一个做什么并不重要,但后者应该 return 在所有必填字段都已填写时为真,否则为假。对于这个例子,为了简单起见,我只使用了一个必填字段:
private bool CanCopyTemplate(object obj)
{
if(//(String.IsNullOrEmpty(Nachname) && String.IsNullOrEmpty(Vorname) && String.IsNullOrEmpty(Angebotstitel) &&
String.IsNullOrEmpty(SelAnrede) //&& String.IsNullOrEmpty(StrasseWohnort) && String.IsNullOrEmpty(PLZ_Wohnort)
//&& String.IsNullOrEmpty(Wohnort)))
)
{
return false;
}
return true;
}
但是,当我填写 SelAnrede(绑定到 Combobox Selected Item 属性 with Update Source Trigger=On 属性 的字符串已更改时,该按钮仍处于禁用状态。 我错过了什么?为什么在视图中更改 SelItem 属性 时未调用 CanExecuteChanged() 方法?为什么 CanCopyTemplate() 方法不再被调用?
这里是 RelayCommand-Class 以获得更好的概述:
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#region Konstruktoren
/// <summary>
/// Erzeugt ein neues Command, das immer ausführen kann.
/// </summary>
/// <param name="execute">Die Ausführungslogik...</param>
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
/// <summary>
/// Erzeugt ein neues Command
/// </summary>
/// <param name="execute">Die Ausführungslogik...</param>
/// <param name="canExecute">Die Logik zum Ausführungsstatus...</param>
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion // Konstruktoren
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameters)
{
return _canExecute == null ? true : _canExecute(parameters);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
event EventHandler ICommand.CanExecuteChanged
{
add
{
//throw new NotImplementedException();
}
remove
{
//throw new NotImplementedException();
}
}
public void Execute(object parameters)
{
_execute(parameters);
}
#endregion // ICommand Members
}
每当设置了在命令的 CanCopyTemplate
方法中检查其值的 属性 时,您应该调用引发其 CanExecuteChanged
事件的命令的方法。
因此,例如,SelAnrede
属性 的 setter 应该像这样实现:
private string _selAnrede;
public string SelAnrede
{
get { return _selAnrede; }
set
{
_selAnrede = value;
OnPropertyChanged(nameof(SelAnrede));
CommandManager.InvalidateRequerySuggested();
}
}
CanExecuteChanged
事件不是“自动”引发的事件,但大多数 ICommand
的实现都有一个为您引发它的方法。你只需要确定你真的调用了它。