Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding to commands in WinForms

Tags:

How can a button be bound to a command in a view model like in WPF with MVVM?

like image 310
Mark Bostleman Avatar asked Nov 06 '09 02:11

Mark Bostleman


People also ask

Is WinForms going away?

As we mentioned above, WinForms is still available but the status of “maintenance mode” likely means it has no long term future. As time passed by, especially in the last 5-10 years, new tools continued to mature and rise in popularity, and each one of them offered many powerful features.

What is a binding source in C#?

The BindingSource component acts as both a conduit and a data source for other controls to bind to. It provides an abstraction of your form's data connection while passing through commands to the underlying list of data.


1 Answers

I was wondering if the same thing could be done and ended writing a simple CommandManager that queries the registered commands (on the Application.Idle event) and uses databinding to change the Enabled state of the control

This is the code I'm using right now:

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;     } } 

and this is an exmaple of how to use it:

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;     } } 

Also if you need the code, I blogged about it here

like image 175
Sebastian Piu Avatar answered Oct 28 '22 01:10

Sebastian Piu