Seb*_*Piu 17
我想知道是否可以完成相同的事情并结束编写一个简单的CommandManager来查询已注册的命令(在Application.Idle事件上)并使用数据绑定来更改控件的Enabled状态
这是我现在使用的代码:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
这是如何使用它的例子:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
此外,如果您需要代码,我在这里写博客
您可以创建一个通用命令绑定类,该类允许将命令绑定到任何继承的类ButtonBase
.
public class CommandBinding<T> where T : ButtonBase
{
private T _invoker;
private ICommand _command;
public CommandBinding(T invoker, ICommand command)
{
_invoker = invoker;
_command = command;
_invoker.Enabled = _command.CanExecute(null);
_invoker.Click += delegate { _command.Execute(null); };
_command.CanExecuteChanged += delegate { _invoker.Enabled = _command.CanExecute(null); };
}
}
Run Code Online (Sandbox Code Playgroud)
然后可以使用以下代码设置命令绑定:
CommandBinding<Button> cmdBinding =
new CommandBinding<Button>(btnCut, CutCommand);
Run Code Online (Sandbox Code Playgroud)
这只是我实现的基础,为您提供一个开始,所以自然会有一些注意事项:
ICommand
接口,因此如果您拥有自己的命令模式实现,则可能必须更改.通用约束也可以更改为Control
暴露Click
事件和Enabled
属性,这意味着命令几乎可以绑定到任何Control.
我之前已将ICommand
对象附加到和对象Tag
的属性上。Button
MenuItem
然后,我只是看看是否可以投射并运行它(如果可以的话),例如:
private void button1_Click(object sender, EventArgs e)
{
ICommand command = ((Control)(sender)).Tag as ICommand;
if (command != null)
{
command.Execute();
}
}
Run Code Online (Sandbox Code Playgroud)
为了更轻松的生活,请尝试对控件进行子类化(例如Button
, MenuItem
)
归档时间: |
|
查看次数: |
14041 次 |
最近记录: |