Skip to content

Hot cs CommandBindingAttribute

Joe Care edited this page Jan 28, 2025 · 1 revision

CommandBindingAttribute

--> Code

When using a MVVM-Pattern you'll have to bind the buttons to the ICommand-Properties of the ViewModel to make this a little more comfortable you can use this Attribute.

// ***********************************************************************
// Assembly         : MVVM-WinForms-Binding
// Author           : Joe Care
// Created          : 21-01-2025
//
// Last Modified By : Mir
// Last Modified On : 26-01-2025
// ***********************************************************************
// <copyright file="FrmMain.cs" company="JC-Soft">
//     Copyright © JC-Soft 2025
// </copyright>
// <summary></summary>
// ***********************************************************************
using System;
using System.Reflection;
using System.Windows.Forms;
using System.Windows.Input;

namespace Calc32.Visual;

[AttributeUsage(AttributeTargets.Field)]
public class CommandBindingAttribute(string cmdName) : Attribute
{
    public string CommandName { get; } = cmdName;

    public void Bind(object viewModel, Control field)
    {
        if (viewModel.GetType().GetProperty(CommandName)?.GetValue(viewModel) is ICommand cmd)
        {
            cmd.CanExecuteChanged += (s, e) => field.Enabled = cmd.CanExecute(field.Tag);
            field.Click += (s, e) => cmd.Execute(field.Tag);
            field.Enabled = cmd.CanExecute(field.Tag);
        }
    }

    public static void Commit(object obj, object dataContext)
    {
        foreach (var field in obj.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
        {
            if (GetCustomAttribute(field, typeof(CommandBindingAttribute)) is CommandBindingAttribute attr
                && field.GetValue(obj) is Control ctrl)
            {
                attr.Bind(dataContext, ctrl);
            }
        }
    }
}

Usage: (in the designer.cs)

   partial class MainForm : Forms
[...]
        [CommandBinding(nameof(ICalculatorViewModel.OperationCommand))]
        private System.Windows.Forms.Button btnClear;
        [CommandBinding(nameof(ICalculatorViewModel.OperationCommand))]
        private System.Windows.Forms.Button btnClearAll;
[...]

and

       public FrmMain(ICalculatorViewModel model)
       {
           InitializeComponent();
           DataContext = model;
           DataContext.PropertyChanged += vmPropertyChanged;

           CommandBindingAttribute.Commit(this,DataContext);
       }

Clone this wiki locally