了解 Prism 中的委托命令
Understanding Delegate Command in Prism
我正在努力理解委托命令(来自 Prism)的用法,我构建了一个虚拟应用程序,我打算在其中执行以下操作。
我的命令是
private readonly DelegateCommand selectAll;
public ICommand SelectAll
{
get { return selectAll; }
}
并将其用作
selectAll= new DelegateCommand(SelectAll,CanSelectAll);
private bool CanSelectAll()
{
if (AllSelectedItems.Count()>3)
{
return true;
}
return false;
}
public IList<Student> AllItemsSelected
{
get => m_Items;
set => Set(ref m_Items, value);
}
当我的 ViewModel 初始化时,我可以看到按钮按预期被禁用,但即使有时这个 AllSelectedItems.count > 3
,它似乎也没有更新并通知 UI。
我做错了什么?
创建命令时,告诉它观察属性 AllItemsSelected
,像这样:
selectAll= new DelegateCommand(SelectAll,CanSelectAll)
.ObservesProperty(() => AllItemsSelected);
这将使命令的状态在每次 AllItemsSelected
更改时更新。
这个功能,ObservesProperty
是 Prism 的一个很好的功能。它允许您设置 one-time 监控该命令状态所依赖的所有属性。
CanSelectAll
方法不会在集合更改时自动调用,毕竟命令应该如何知道何时重新评估条件?您必须明确告诉它这样做。
一个ICommand
公开了一个CanExecutChanged
event that must be raised to notify the element binding the command to call the CanExecute
方法来评估命令是否可以执行。这通常启用或禁用 [=66=] 中的元素,例如一个Button
。何时以及如何引发此事件取决于 ICommand
接口的具体实现。
在 DelegateCommand
s 的 Prism 中,这可以通过两种不同的方式完成。
在命令上调用 RaiseCanExecuteChanged
。这可以在 AllItemsSelected
属性.
的 setter 中完成
public IList<Student> AllItemsSelected
{
get => m_Items;
set
{
Set(ref m_Items, value);
selectAll.RaiseCanExecuteChanged();
}
}
另一种方法是使用 ObservesProperty
method when instantiating the command. You pass a lambda for the property to be observed and the command will automatically raise the CanExecuteChanged
event once a PropertyChanged
event is raised for it. That means this mechanism only works if your view model implements INotifyPropertyChanged
并且你的 属性 加注 PropertyChanged
.
selectAll= new DelegateCommand(SelectAll, CanSelectAll).ObservesProperty(() => AllItemsSelected);
选择哪种机制由您决定。对于您的具体情况,了解 AllItemsSelected
的变化方式很重要。如果您总是在选择更改后分配一个新集合,则上面的示例将起作用,因为每次调用 属性 的 setter 并引发 PropertyChanged
,因此 ObservesProperty
将拾取零钱并调用 CanExecutChanged
例如。
但是,如果您重复使用同一个集合,例如仅从其中添加和删除项目,这将不起作用,因为实际的集合对象不会更改,这意味着不会调用 setter 也不会调用 PropertyChanged
。在这种情况下,将对 RaiseCanExecuteChanged
的调用放入添加、删除或修改集合的方法中。
以防集合在其他地方被修改,例如项目通过 UI 直接添加到集合中,您必须使用支持通知集合更改的集合类型,如 ObservableCollection<T>
(通过 CollectionChanged
事件)。您可以向 CollectionChanged
添加一个处理程序,它调用 RaiseCanExecuteChanged
.
public class MyViewModel : BindableBase
{
private readonly DelegateCommand _selectAll;
public MyViewModel()
{
_selectAll = new DelegateCommand(ExecuteSelectAll, CanExecuteSelectAll);
AllSelectedItems = new ObservableCollection<Student>();
AllSelectedItems.CollectionChanged += OnAllSelectedItemsChanged;
}
public ICommand SelectAll => _selectAll;
public ObservableCollection<Student> AllSelectedItems
{
get => m_Items;
set => Set(ref m_Items, value);
}
private void ExecuteSelectAll()
{
// ...your code.
}
private bool CanExecuteSelectAll()
{
return AllSelectedItems.Count > 3;
}
private void OnAllSelectedItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
_selectAll.RaiseCanExecuteChanged();
}
}
我正在努力理解委托命令(来自 Prism)的用法,我构建了一个虚拟应用程序,我打算在其中执行以下操作。
我的命令是
private readonly DelegateCommand selectAll;
public ICommand SelectAll
{
get { return selectAll; }
}
并将其用作
selectAll= new DelegateCommand(SelectAll,CanSelectAll);
private bool CanSelectAll()
{
if (AllSelectedItems.Count()>3)
{
return true;
}
return false;
}
public IList<Student> AllItemsSelected
{
get => m_Items;
set => Set(ref m_Items, value);
}
当我的 ViewModel 初始化时,我可以看到按钮按预期被禁用,但即使有时这个 AllSelectedItems.count > 3
,它似乎也没有更新并通知 UI。
我做错了什么?
创建命令时,告诉它观察属性 AllItemsSelected
,像这样:
selectAll= new DelegateCommand(SelectAll,CanSelectAll)
.ObservesProperty(() => AllItemsSelected);
这将使命令的状态在每次 AllItemsSelected
更改时更新。
这个功能,ObservesProperty
是 Prism 的一个很好的功能。它允许您设置 one-time 监控该命令状态所依赖的所有属性。
CanSelectAll
方法不会在集合更改时自动调用,毕竟命令应该如何知道何时重新评估条件?您必须明确告诉它这样做。
一个ICommand
公开了一个CanExecutChanged
event that must be raised to notify the element binding the command to call the CanExecute
方法来评估命令是否可以执行。这通常启用或禁用 [=66=] 中的元素,例如一个Button
。何时以及如何引发此事件取决于 ICommand
接口的具体实现。
在 DelegateCommand
s 的 Prism 中,这可以通过两种不同的方式完成。
在命令上调用
的 setter 中完成RaiseCanExecuteChanged
。这可以在AllItemsSelected
属性.public IList<Student> AllItemsSelected { get => m_Items; set { Set(ref m_Items, value); selectAll.RaiseCanExecuteChanged(); } }
另一种方法是使用
ObservesProperty
method when instantiating the command. You pass a lambda for the property to be observed and the command will automatically raise theCanExecuteChanged
event once aPropertyChanged
event is raised for it. That means this mechanism only works if your view model implementsINotifyPropertyChanged
并且你的 属性 加注PropertyChanged
.selectAll= new DelegateCommand(SelectAll, CanSelectAll).ObservesProperty(() => AllItemsSelected);
选择哪种机制由您决定。对于您的具体情况,了解 AllItemsSelected
的变化方式很重要。如果您总是在选择更改后分配一个新集合,则上面的示例将起作用,因为每次调用 属性 的 setter 并引发 PropertyChanged
,因此 ObservesProperty
将拾取零钱并调用 CanExecutChanged
例如。
但是,如果您重复使用同一个集合,例如仅从其中添加和删除项目,这将不起作用,因为实际的集合对象不会更改,这意味着不会调用 setter 也不会调用 PropertyChanged
。在这种情况下,将对 RaiseCanExecuteChanged
的调用放入添加、删除或修改集合的方法中。
以防集合在其他地方被修改,例如项目通过 UI 直接添加到集合中,您必须使用支持通知集合更改的集合类型,如 ObservableCollection<T>
(通过 CollectionChanged
事件)。您可以向 CollectionChanged
添加一个处理程序,它调用 RaiseCanExecuteChanged
.
public class MyViewModel : BindableBase
{
private readonly DelegateCommand _selectAll;
public MyViewModel()
{
_selectAll = new DelegateCommand(ExecuteSelectAll, CanExecuteSelectAll);
AllSelectedItems = new ObservableCollection<Student>();
AllSelectedItems.CollectionChanged += OnAllSelectedItemsChanged;
}
public ICommand SelectAll => _selectAll;
public ObservableCollection<Student> AllSelectedItems
{
get => m_Items;
set => Set(ref m_Items, value);
}
private void ExecuteSelectAll()
{
// ...your code.
}
private bool CanExecuteSelectAll()
{
return AllSelectedItems.Count > 3;
}
private void OnAllSelectedItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
_selectAll.RaiseCanExecuteChanged();
}
}