Привязка к командам в WinForms

Я бы, вероятно, сбил что-то, используя атрибуты, а затем класс преобразования, чтобы преобразовать подходящие атрибуты в примитивы битового поля. Что-то вроде ...

using System;

namespace BitfieldTest
{
    [global::System.AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
    sealed class BitfieldLengthAttribute : Attribute
    {
        uint length;

        public BitfieldLengthAttribute(uint length)
        {
            this.length = length;
        }

        public uint Length { get { return length; } }
    }

    static class PrimitiveConversion
    {
        public static long ToLong<T>(T t) where T : struct
        {
            long r = 0;
            int offset = 0;

            // For every field suitably attributed with a BitfieldLength
            foreach (System.Reflection.FieldInfo f in t.GetType().GetFields())
            {
                object[] attrs = f.GetCustomAttributes(typeof(BitfieldLengthAttribute), false);
                if (attrs.Length == 1)
                {
                    uint fieldLength  = ((BitfieldLengthAttribute)attrs[0]).Length;

                    // Calculate a bitmask of the desired length
                    long mask = 0;
                    for (int i = 0; i < fieldLength; i++)
                        mask |= 1 << i;

                    r |= ((UInt32)f.GetValue(t) & mask) << offset;

                    offset += (int)fieldLength;
                }
            }

            return r;
        }
    }

    struct PESHeader
    {
        [BitfieldLength(2)]
        public uint reserved;
        [BitfieldLength(2)]
        public uint scrambling_control;
        [BitfieldLength(1)]
        public uint priority;
        [BitfieldLength(1)]
        public uint data_alignment_indicator;
        [BitfieldLength(1)]
        public uint copyright;
        [BitfieldLength(1)]
        public uint original_or_copy;
    };

    public class MainClass
    {
        public static void Main(string[] args)
        {
            PESHeader p = new PESHeader();

            p.reserved = 3;
            p.scrambling_control = 2;
            p.data_alignment_indicator = 1;

            long l = PrimitiveConversion.ToLong(p);


            for (int i = 63; i >= 0; i--)
            {
                Console.Write( ((l & (1l << i)) > 0) ? "1" : "0");
            }

            Console.WriteLine();

            return;
        }
    }
}

Что производит ожидаемый ... 000101011. Конечно, для этого требуется больше проверки ошибок и немного более удобного набора текста, но концепция (я думаю) звучит, многократно используется и позволяет вам выбивать легко поддерживаемые структуры дюжиной.

adamw

19
задан Mark Bostleman 6 November 2009 в 02:44
поделиться

4 ответа

Я прикрепил объекты ICommand к свойству Tag объектов Button и MenuItem до .

Затем я просто проверяю, смогу ли я его применить и запустить, если смогу, например:

private void button1_Click(object sender, EventArgs e)
{
    ICommand command = ((Control)(sender)).Tag as ICommand;

    if (command != null)
    {
        command.Execute();
    }
}

Для еще более легкой жизни попробуйте создать подкласс элементов управления (например, Button , MenuItem )

2
ответ дан 30 November 2019 в 00:43
поделиться

Мой подход основан на ответе Гейла, но использовании дополнительного метода и создании закрепления, доступного для lifeycle управления:

    public static class ButtonExtensions
    {
        public static IDisposable Bind(this ButtonBase invoker, ICommand command)
        {
            void Click(object sender, EventArgs args) => command.Execute(null);
            void CanExecuteChanged(object sender, EventArgs args) => invoker.Enabled = command.CanExecute(null);

            invoker.Enabled = command.CanExecute(null);

            invoker.Click += Click;
            command.CanExecuteChanged += CanExecuteChanged;

            return Disposable.Create(() =>
            {
                invoker.Enabled = false;
                invoker.Click -= Click;
                command.CanExecuteChanged -= CanExecuteChanged;
            });
        }
    }

Вы можете использовать его как это:

private List<IDisposable> Disposables { get; } = new List<IDisposable>();
private ICommand MyCommand { get; }

public MyControl()
{
    MyCommand = DelegateCommand.Create(() => ...);
    Disposables.Add(myButton.Bind(MyCommand));
}

~MyControl()
{
    foreach(var disposable in Disposables)
    {
        disposable?.Dispose();
    }
}

Однако можно было бы предпочесть использовать ReactiveUI, у которого есть родная поддержка этого:

ReactiveUI 6.0 и WinForms, связывающий

1
ответ дан 30 November 2019 в 00:43
поделиться

Я не думаю, что вы можете сделать это напрямую, но как насчет использования обработчика нажатия кнопки для вызова команды? Это не так чисто, как WPF, но вы все равно получаете разделение.

0
ответ дан 30 November 2019 в 00:43
поделиться

Я бы рекомендовал реализовать INotifyPropertyChanged , вы можете использовать его как в WinForms, так и в WPF. См. здесь для введения и здесь для дополнительной информации.

0
ответ дан 30 November 2019 в 00:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: