【问题标题】:How to move a command handler to another file如何将命令处理程序移动到另一个文件
【发布时间】:2019-04-17 20:44:55
【问题描述】:

我从Microsoft Examples 中找到了一个自定义路由命令示例,它运行良好。

<Window x:Class="CustomRoutedCommand.MainWindow"
        ...
        xmlns:local="clr-namespace:CustomRoutedCommand">
    <Window.CommandBindings>
        <CommandBinding Command="{x:Static local:MainWindow.ColorCmd}"
                    Executed="ColorCmdExecuted"
                    CanExecute="ColorCmdCanExecute"/>
    </Window.CommandBindings>

void ColorCmdExecuted(object sender, ExecutedRoutedEventArgs e)void ColorCmdCanExecute(object sender, CanExecuteRoutedEventArgs e)MainWindow.cs 中定义。

如果我将这两个处理程序移动到 xxxx.cs,如何更改 XAML?

编辑,添加更多信息

命令处理程序在MainWindow.cs中定义,我将代码剪切并粘贴到另一个文件中,如下所示,然后编译出错。 错误 CS1061“MainWindow”不包含“ColorCmdExecuted”的定义

// xxxx.cs
namespace CustomRoutedCommand
{
    public class xxxx
    {
        // ExecutedRoutedEventHandler for the custom color command.
        private void ColorCmdExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            var target = e.Source as Panel;
            if (target != null)
            {
                target.Background = target.Background == Brushes.AliceBlue ? Brushes.LemonChiffon : Brushes.AliceBlue;
            }
        }

        // CanExecuteRoutedEventHandler for the custom color command.
        private void ColorCmdCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (e.Source is Panel)
            {
                e.CanExecute = true;
            }
            else
            {
                e.CanExecute = false;
            }
        }
    }
}

【问题讨论】:

  • 您确定要使用Static 命令吗?并且来质疑你可以移动它是问题吗?
  • 实际上不确定,我是 WPF 初学者。我接受任何更好的建议。而且,当我将“ColorCmdExecuted”移动到另一个文件时出现错误。 错误 CS1061“MainWindow”不包含“ColorCmdExecuted”的定义
  • 也可以发布移动的文件。我的意思是你把那个文件代码放在哪里。
  • 在同一个命名空间下新建一个类(xxxx.cs),从MainWindow.cs中剪切代码并粘贴到xxxx.cs中。
  • 您能从新文件中发布更多代码吗?特别是,这些命令仍然是MainWindow 的一部分,还是您定义了一个完全不同的类?

标签: c# wpf xaml


【解决方案1】:

您不能将在 XAML 标记中挂钩的实际事件处理程序移动到另一个类,但您可以在另一个类中实现逻辑:

public partial class MainWindow : Window
{
    public static RoutedCommand ColorCmd = new RoutedCommand();

    public MainWindow()
    {
        InitializeComponent();
    }

    private void ColorCmdExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        xxxx.ColorCmdExecuted(e.Source);
    }

    private void ColorCmdCanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = xxxx.ColorCmdCanExecute(e.Source);
    }
}

public class xxxx
{
    public static void ColorCmdExecuted(object parameter)
    {
        var target = parameter as Panel;
        if (target != null)
        {
            target.Background = target.Background == Brushes.AliceBlue ? Brushes.LemonChiffon : Brushes.AliceBlue;
        }
    }

    public static bool ColorCmdCanExecute(object parameter)
    {
        return parameter is Panel;
    }
}

您可能希望将RoutedCommand 替换为ICommand 接口的自定义实现,当您直接执行命令时可以执行一些操作:

public class RelayCommand : ICommand
{
    private Action<object> _execute;
    private Predicate<object> _canExecute;

    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        _execute = execute;
        _canExecute = canExecute;
    }
    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        if (_canExecute == null)
            return true;
        return _canExecute(parameter);
    }

    public void Execute(object parameter)
    {
        if (_execute != null)
            _execute(parameter);
    }
}

public partial class MainWindow : Window
{
    public static RelayCommand ColorCmd = new RelayCommand(xxxx.ColorCmdExecuted, null);

    public MainWindow()
    {
        InitializeComponent();
    }
}

public class xxxx
{
    public static void ColorCmdExecuted(object parameter)
    {
        var target = parameter as Panel;
        if (target != null)
        {
            target.Background = target.Background == Brushes.AliceBlue ? Brushes.LemonChiffon : Brushes.AliceBlue;
        }
    }
}

XAML:

<Button Command="{x:Static local:MainWindow.ColorCmd}" Content="CommandTarget = FristStackPanel" />

有关此概念的更多信息,请参阅this 博客文章。

【讨论】:

    【解决方案2】:

    您可以继续使用static 命令,但更常见的是使用称为RelayCommandICommand 实现。这使我们可以更轻松地利用 MVVM,以便您的视图模型模型可以处理命令。这是ICommand的基本示例实现:

    public class RelayCommand : ICommand
    {
        private Predicate<object> _canExecute;
        private Action<object> _execute;
    
        public RelayCommand(Predicate<object> canExecute, Action<object> execute)
        {
            _canExecute = canExecute;
            _execute = execute;
        }
    
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
    
        public bool CanExecute(object parameter)
        {
            return _canExecute(parameter);
        }
    
        public void Execute(object parameter)
        {
            _execute(parameter);
        }
    }
    

    然后,您可以将RelayCommand 作为属性添加到您的视图模型中,如下所示:

    public class ViewModel : ViewModelBase
    {
        private RelayCommand colorCmd;
        public ICommand ColorCmd
        {
            get
            {
                colorCmd ?? colorCmd = new RelayCommand(p => ColorCmdCanExecute(), p => ColorCmdExectued());
                return colorCmd;
            }
        }
    
        private bool ColorCmdCanExecute()
        {
            //CanExecute code here
            ...
        }
    
        private void ColorCmdExecuted()
        {
            //Command execute code here
            ...
        }
    }
    

    有关 MVVM 和ICommand 实现的更多信息,有很多资源。 This one 对于 WPF 初学者来说非常容易理解,并且应该让您对如何进行有更多的了解。

    【讨论】:

      猜你喜欢
      • 2013-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-21
      • 2011-06-12
      • 2019-07-13
      • 2013-11-11
      • 1970-01-01
      相关资源
      最近更新 更多