我正在遵循有关 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>
    

    解决方案结构:

    c# - 为什么必须要公开ICommand对象才能在WPF中正常工作?-LMLPHP

    最佳答案

    绑定(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/

    10-12 03:58