【问题标题】:Getting to grips with the iCommand Design pattern掌握命令设计模式
【发布时间】:2016-06-17 06:49:42
【问题描述】:

正在尝试学习 WPF,并且我已经阅读/测试了教程。

这是我的场景:

一个 wpf C# 应用程序。 我的主窗口上有一个 UserControl。 这个 UserControl 上有 4 个按钮。 我的意图是将每个命令(单击)事件绑定到每个按钮。 但是,我不想将每个按钮绑定到自己的类,而是想将这 4 个按钮的每个命令事件绑定到 1 个类。 所以..我想将参数传递给 CanExecute 和 Execute 方法,并且我正在/正在尝试将枚举传递给这些方法。 所以..到目前为止我得到的是:

public event EventHandler CanExecuteChanged
{
    add { CommandManager.RequerySuggested += value; }
    remove { CommandManager.RequerySuggested -= value; }
}

public bool CanExecute(object parameter)
{
    var commandChosen= parameter as TopMenuCommands;
    return true;
}

public void Execute(object parameter)
{
    var buttonChosen = parameter as MenuCommandObject;
    evMenuChange(buttonChosen);
}

public enum enTopMenuCommands
{
    Button1 = 0,
    Button1 = 1,
    Button1 = 2,
    Button1 = 3
}

但是我怎样才能将它与我的主窗口联系起来呢?

我承认我可能完全错了,但我仍在学习。

谢谢

【问题讨论】:

    标签: c# wpf


    【解决方案1】:

    我的ICommand 实现在构造函数中采用Action<object>Execute 方法刚刚调用了Action

    这样每个命令的逻辑都是从创建的地方传入的。

    ICommand 实现:

    public class SimpleCommand : ICommand
        {
            public event EventHandler CanExecuteChanged;
    
            private Action<object> _execute;
            private Func<bool> _canExecute;
    
            public SimpleCommand(Action<object> execute) : this(execute, null) { }
    
            public SimpleCommand(Action<object> execute, Func<bool> canExecute)
            {
                _execute = execute;
                _canExecute = canExecute;
            }
    
            public bool CanExecute(object param)
            {
                if (_canExecute != null)
                {
                    return _canExecute.Invoke();
                }
                else
                {
                    return true;
                }
            }
    
            public void Execute(object param)
            {
                _execute.Invoke(param);
            }
    
            protected void OnCanExecuteChanged()
            {
                CanExecuteChanged?.Invoke(this,EventArgs.Empty);
            }
    
            #region Common Commands
            private static SimpleCommand _notImplementedCommand;
            public static ICommand NotImplementedCommand
            {
                get
                {
                    if (_notImplementedCommand == null)
                    {
                        _notImplementedCommand = new SimpleCommand(o => { throw new NotImplementedException(); });
                    }
                    return _notImplementedCommand;
                }
            }
            #endregion
        }
    

    用法示例:

    using System;
    using System.Data.Entity;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Windows.Input;
    using SqlMetaQuery.Model;
    using SqlMetaQuery.ViewModels.ScriptList;
    using SqlMetaQuery.Windows.EditQuery;
    using WpfLib;
    
    namespace SqlMetaQuery.Windows.Main
    {
        class MainWindowVm : WpfLib.ViewModel
        {
            public MainWindowVm()
            {
                if (!IsInDesignMode)
                {
                    using (Context db = new Context())
                    {
                        ScriptTree = new ScriptTreeVm(db.Tags
                            .Include(t => t.Scripts)
                            .OrderBy(t => t.Name));
    
                        CurrentUser = db.Users.Where(u => u.UserName == "Admin").AsNoTracking().FirstOrDefault();
                        MiscTag = db.Tags.Where(t => t.Name == "Misc").AsNoTracking().FirstOrDefault();
    
                    }
                }
            }
    
            public ScriptTreeVm ScriptTree { get; }
    
            public Model.User CurrentUser { get; }
    
            private Model.Tag MiscTag { get; }
    
            private void SaveScript(Model.Script script)
            {
                using (var context = new Model.Context())
                {
                    context.Scripts.Add(script);
                    context.SaveChanges();
                }
            }
    
            #region Commands
    
            private ICommand _exitCommand;
            public ICommand ExitCommand
            {
                get
                {
                    if (_exitCommand == null)
                    {
                        _exitCommand = new SimpleCommand((arg) => WindowManager.CloseAll());
                    }
                    return _exitCommand;
                }
            }
    
            private ICommand _newScriptCommand;
            public ICommand NewScriptCommand
            {
                get
                {
                    if (_newScriptCommand == null)
                    {
                        _newScriptCommand = new SimpleCommand((arg) =>
                        {
                            var script = new Model.Script()
                            {
                                Title = "New Script",
                                Description = "A new script.",
                                Body = ""
                            };
                            script.Tags.Add(MiscTag);
                            var vm = new EditQueryWindowVm(script);
                            var result = WindowManager.DisplayDialogFor(vm);
    
                            // if (result.HasValue && result.Value)
                            //{
                            script.VersionCode = Guid.NewGuid();
                            script.CreatedBy = CurrentUser;
                            script.CreatedDate = DateTime.Now.ToUniversalTime();
                            SaveScript(script);
                            //}
                        });
                    }
                    return _newScriptCommand;
                }
            }
    
    
            #endregion
        }
    }
    

    XAML:

    <Window x:Class="SqlMetaQuery.Windows.Main.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:controls="clr-namespace:SqlMetaQuery.Controls"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:local="clr-namespace:SqlMetaQuery.Windows.Main"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            Title="MainWindow"
            Width="800"
            Height="600"
            d:DataContext="{d:DesignInstance Type=local:MainWindowVm}"
            mc:Ignorable="d">
        <DockPanel>
            <Menu DockPanel.Dock="Top">
                <MenuItem Header="File">
                    <MenuItem Command="{Binding Path=NewScriptCommand}" Header="New Script..." />
                    <Separator />
                    <MenuItem Command="{Binding Path=ExitCommand}" Header="Exit" />
                </MenuItem>
            </Menu>
            <Grid Margin="8">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="250" />
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <controls:ScriptTree Grid.Row="0"
                                     Grid.Column="0"
                                     DataContext="{Binding Path=ScriptTree}" />
                <GridSplitter Grid.Row="0"
                              Grid.Column="1"
                              Width="8"
                              VerticalAlignment="Stretch"
                              ResizeBehavior="PreviousAndNext" />
                <Grid Grid.Row="0" Grid.Column="2">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="8" />
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>
                    <Border Grid.Row="0" Style="{StaticResource BorderStandard}">
                        <TextBlock Text="{Binding Path=ScriptTree.CurrentScript.Title}" />
                    </Border>
                    <Border Grid.Row="3" Style="{StaticResource BorderStandard}">
                        <TextBlock Text="{Binding Path=ScriptTree.CurrentScript.Body}" />
                    </Border>
                </Grid>
            </Grid>
        </DockPanel>
    
    </Window>
    

    【讨论】:

    • 嗨,我知道我在这里看起来一定很昏暗,但是你可以在我正在尝试做的事情的背景下给我一个例子吗?什么是最佳实践?谢谢
    • 更新了实现和使用示例。
    • 哇!谢谢。让我消化一下,然后回复你。很高兴你这样做
    • 我刚刚意识到,我给您的使用示例可能有点令人困惑,因为它实际上是一个在我的应用程序中处理“命令”的 ICommand。让我为您找到一个您不必处理尝试解析的问题...
    • :) 我正要发评论说。你明明知道你的东西,让我觉得自己很渺小。我怀疑你是否曾经失业过!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-29
    • 1970-01-01
    • 1970-01-01
    • 2013-04-28
    • 2011-02-15
    • 2011-01-02
    相关资源
    最近更新 更多