c# - 绑定(bind)到 WinForms 中的命令

标签 c# winforms mvvm

如何将按钮绑定(bind)到 View 模型中的命令,例如使用 MVVM 的 WPF?

最佳答案

我想知道是否可以做同样的事情,并结束编写一个简单的 CommandManager 来查询注册的命令(在 Application.Idle 事件上)并使用数据绑定(bind)来更改控件的启用状态

这是我现在正在使用的代码:

public class CommandManager: Component
{
    private IList<ICommand> Commands { get; set; }
    private IList<ICommandBinder> Binders { get; set; }

    public CommandManager()
    {
        Commands = new List<ICommand>();

        Binders = new List<ICommandBinder>
                      {
                          new ControlBinder(),
                          new MenuItemCommandBinder()
                      };

        Application.Idle += UpdateCommandState;
    }

    private void UpdateCommandState(object sender, EventArgs e)
    {
        Commands.Do(c => c.Enabled);
    }

    public CommandManager Bind(ICommand command, IComponent component)
    {
        if (!Commands.Contains(command))
            Commands.Add(command);

        FindBinder(component).Bind(command, component);
        return this;
    }

    protected ICommandBinder FindBinder(IComponent component)
    {
        var binder = GetBinderFor(component);

        if (binder == null)
            throw new Exception(string.Format("No binding found for component of type {0}", component.GetType().Name));

        return binder;
    }

    private ICommandBinder GetBinderFor(IComponent component)
    {
        var type = component.GetType();
        while (type != null)
        {
            var binder = Binders.FirstOrDefault(x => x.SourceType == type);
            if (binder != null)
                return binder;

            type = type.BaseType;
        }

        return null;
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
            Application.Idle -= UpdateCommandState;

        base.Dispose(disposing);
    }
}

public static class Extensions
{
    public static void Do<T>(this IEnumerable<T> @this, Func<T, object> lambda)
    {
        foreach (var item in @this)
            lambda(item);
    }
}
public abstract class CommandBinder<T> : ICommandBinder where T: IComponent
{
    public Type SourceType
    {
        get { return typeof (T); }
    }

    public void Bind(ICommand command, object source)
    {
        Bind(command, (T) source); 
    }

    protected abstract void Bind(ICommand command, T source);
}

public class ControlBinder: CommandBinder<Control>
{
    protected override void Bind(ICommand command, Control source)
    {
        source.DataBindings.Add("Enabled", command, "Enabled");
        source.DataBindings.Add("Text", command, "Name");
        source.Click += (o, e) => command.Execute();
    }
}

public class MenuItemCommandBinder : CommandBinder<ToolStripItem>
{
    protected override void Bind(ICommand command, ToolStripItem source)
    {
        source.Text = command.Name;
        source.Enabled = command.Enabled;
        source.Click += (o, e) => command.Execute();

        command.PropertyChanged += (o, e) => source.Enabled = command.Enabled;
    }
}

这是如何使用它的示例:

public partial class Form1 : Form
{
    private CommandManager commandManager;

    public ICommand CommandA { get; set; }
    public ICommand CommandB { get; set; }

    public bool condition;

    public Form1()
    {
        InitializeComponent();

        commandManager = new CommandManager();

        CommandA = new DelegateCommand("Command 1", OnTrue, OnExecute);
        CommandB = new DelegateCommand("Command 2", OnFalse, OnExecute);

        commandManager.Bind(CommandA, button1);
        commandManager.Bind(CommandB, button2);

        commandManager.Bind(CommandA, command1ToolStripMenuItem);
        commandManager.Bind(CommandB, command2ToolStripMenuItem);
    }

    private bool OnFalse()
    {
        return !condition;
    }

    private bool OnTrue()
    {
        return condition;
    }

    private void OnExecute()
    {
        condition = !condition;
    }
}

此外,如果您需要代码,我在博客上介绍了它 here

关于c# - 绑定(bind)到 WinForms 中的命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1685088/

相关文章:

c# - TextInfo.ToTitleCase 对于全部大写字符串没有按预期工作

c# - 标签尺寸不正确

c# - Richtextbox 在新文本前加上颜色

c# - 检查我的 Windows 应用程序是否正在运行

vb.net - Silverlight中Prism MVVM的VB.net示例

wpf - 解析结构图中的窗口或如何管理 WPF MVVM 中的多个窗口?

silverlight - 当ViewModel属性更改时,如何启动动画?

javascript - 在 JS-asp.net MVC 中使用@Url.Action

c# - Hangfire 使用 MongoDB 执行长时间运行的后台作业不断重启

c# - .Net Socket 不响应远程断开连接?