我正在遵循有关 Pluralsight 的类(class),名为“实用MVVM ”。在本类(class)的第4个模块中,作者解释了如何使用命令,这就是我遇到这个奇怪的问题的时候。除了一个区别之外,我编写的代码几乎与视频中的代码相同。我的本地ICommand
变量被声明为private
而不是public
。
当我单击绑定(bind)设置为属于EditCoffee()
命令的EditCommand
方法的按钮时,将发生以下情况:
ICommand EditCommand
声明为,公共(public)或内部,则在EditCoffee()
类中执行Execute()
和CanExecute()
后执行CustomCommand
方法。 ICommand EditCommand
声明为私有(private)或保护的时,方法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>
解决方案结构:
最佳答案
绑定(bind)不是魔术。它是采用您的XAML绑定(bind)声明的代码:
<Button Command="{Binding EditCommand}"
并在您的类的DataContext中查找该名称的属性
EditCommand
。XAML View 是与ViewModel不同的类,因此,它只能访问ViewModel上的公共(public)属性,这是有道理的。甚至内部属性也超出范围,因为在WPF库中,试图访问它的是绑定(bind)代码,而不是您自己的 View 代码。
关于c# - 为什么必须要公开ICommand对象才能在WPF中正常工作?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49095263/