为什么必须公开ICommand对象才能在WPF中正常工作?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么必须公开ICommand对象才能在WPF中正常工作?相关的知识,希望对你有一定的参考价值。
我正在关注Pluralsight的一门名为“实用MVVM”的课程。在本课程的第4单元中,作者解释了如何使用命令,当我遇到这个奇怪的问题时。我写了几乎与视频中相同的代码,除了一个区别。我当地的ICommand
变量被宣布为private
而不是public
。
当我单击具有绑定设置的按钮时,会发生以下情况:属于EditCoffee()
命令的方法EditCommand
:
- 当
ICommand EditCommand
被宣布为公共或内部时,方法EditCoffee()
在Execute()
类中执行CanExecute()
和CustomCommand
后执行。 - 当
ICommand EditCommand
被声明为私有或受保护时,方法EditCoffee()
永远不会被执行,并且不会在Execute()
类中执行CanExecute()
和CustomCommand
。
值得一提的是,LoadCommands()
在两种情况下均被触发。
CoffeeOverviewViewModel:
using JoeCoffeeStore.StockManagement.App.Services;
using JoeCoffeeStore.StockManagement.App.Utility;
using JoeCoffeeStore.StockManagement.Model;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
namespace JoeCoffeeStore.StockManagement.App.ViewModel
{
public class CoffeeOverviewViewModel : INotifyPropertyChanged
{
// INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
// Commands
private ICommand EditCommand { get; set; }
// Data Service
private CoffeeDataService _coffeeDataService;
// Properties
private ObservableCollection<Coffee> _coffees;
public ObservableCollection<Coffee> Coffees
{
get{ return _coffees; }
set
{
_coffees = value;
OnPropertyChanged();
}
}
private Coffee _selectedCoffee;
public Coffee SelectedCoffee
{
get { return _selectedCoffee; }
set
{
_selectedCoffee = value;
OnPropertyChanged();
}
}
// Constructor
public CoffeeOverviewViewModel()
{
_coffeeDataService = new CoffeeDataService();
LoadData();
LoadCommands();
}
private void LoadCommands()
{
EditCommand = new CustomCommand(EditCoffee, CanEditCoffee);
}
private void EditCoffee(object obj)
{
//TODO
}
private bool CanEditCoffee(object obj)
{
if (SelectedCoffee != null)
return true;
return false;
}
private void LoadData()
{
Coffees = new ObservableCollection<Coffee>(_coffeeDataService.GetAllCoffees());
}
}
}
CustomCommand.cs:
using System;
using System.Windows.Input;
namespace JoeCoffeeStore.StockManagement.App.Utility
{
public class CustomCommand : ICommand
{
private Action<object> _execute;
private Predicate<object> _canExecute;
public CustomCommand(Action<object> execute, Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
public bool CanExecute(object parameter)
{
bool b = _canExecute == null ? true : _canExecute(parameter);
return b;
}
public void Execute(object parameter)
{
_execute(parameter);
}
}
}
CoffeeOverviewView.xaml:
<StackPanel Grid.Row="7">
<Button Command="{Binding EditCommand}" Content="Edit coffee"/>
</StackPanel>
解决方案结构
答案
绑定不是魔术。它的代码采用您的XAML绑定声明:
<Button Command="{Binding EditCommand}"
并在类的DataContext中查找该名称的属性EditCommand
。
您的XAML视图是一个与ViewModel不同的类,因此它只能访问ViewModel上的公共属性。甚至内部属性都超出范围,因为它是试图在WPF库中访问它的绑定代码,而不是您自己的视图代码。
以上是关于为什么必须公开ICommand对象才能在WPF中正常工作?的主要内容,如果未能解决你的问题,请参考以下文章
2022-03-23 WPF面试题 WPF中的命令设计模式和ICommand是什么?
2022-03-23 WPF面试题 WPF中的命令设计模式和ICommand是什么?