通过处理程序传递自定义EventArgs [英] Passing custom EventArgs through Handler

查看:62
本文介绍了通过处理程序传递自定义EventArgs的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

标题用词不好,但这是我能不加解释地解释的最好的结果.

The title was badly worded, but it's the best I could explain in without going into detail.

首先,我有一个简单的类正在使用(我想...)来处理我的事件.  (我对事件处理完全陌生) 这就是它的样子.

First I have a simple class that I'm using (I guess...) to handle my events.  (I'm totally new to event handling)  Here is what it looks like.

using System;

namespace FrancescoMagliocco.FMScreenRecorder.Core.Events
{
    public class RaiseEventEventArgs : EventArgs
    {
        public static RaiseEventEventArgs Allow = new RaiseEventEventArgs(true);
        public static RaiseEventEventArgs Forbid = new RaiseEventEventArgs();

        public bool Raise { get; }

        public RaiseEventEventArgs(bool raise = false) { this.Raise = raise; }
    }
}

然后我有两种用于实际处理事件的方法.

I then have two methods that I am using to actually handle the event.

        private void MainMenuSubMenuItemHandler(object sender, EventArgs eventArgs)
        {
            var menuItem = sender as MenuItem;
            var menuItemName = menuItem?.Name;


            if (menuItemName == this.closeSbMnTm.Name)
            {
#warning This may not allow the 'OnClosing' event to be triggered, therefore not allowing the settings to be updated.
                Application.ExitThread();
                return;
            }

            switch (menuItemName)
            {
                case RecordAudioSbMnTm:
                case RecordMicrophoneSbMnTm:
                case RecordSystemAudioSbMnTm:
                    var tuple = this._menuItemToMenuItemsAndCheckBoxs[menuItem];
                    var menuItems = tuple.Item1;
                    var checkBox = tuple.Item2;

                    /*
                     * Checks not only if the menuItem is checked, but is also changes its checked state if it's Enabled.
                     * Alreach checked if explicit check for it being Enabled was needed, and it's not.
                     */
                    var isChecked = menuItem.Checked = checkBox.Checked = !menuItem.Checked;

                    if (((RaiseEventEventArgs)eventArgs).Raise) {
                        this.CheckBoxHandler(checkBox, RaiseEventEventArgs.Forbid);
                    }

                    if (menuItems.Length > 1)
                    {
                        /*
                         * This part will only be reached (So far) if the case is 'RecordAudioSbMnTm', and will only set the
                         * 'RecordMicrophoneSbMnTm' and 'RecordSystemAudioSbMnTm' to be Enabled based on 'isChecked',
                         * it will also set the 'this.configureSbMnTm' Enabled state based on 'isChecked' as well, but NOT
                         * the 'this.configMicrophoneCodecSbMnTm' or 'this.configSystemAudioCodecSbMnTm' Enabled states.
                         */
                        foreach (var subMenuItem in menuItems) { subMenuItem.Enabled = isChecked; }
                    }
                    else
                    { menuItems.First().Enabled = isChecked; }

                    break;
                case ConfigMicrophoneCodecSbMnTm:
                case ConfigSystemAudioCodecSbMnTm:
                    break;
            }
        }

        private void CheckBoxHandler(object sender, EventArgs eventArgs)
        {
            var checkBox = sender as CheckBox;

            switch (checkBox?.Name)
            {

                // Braces are used to allow the use of field 'control' more than once.
                case CustomFrameRateChckBx:
                {
                        Control control;

                    /*
                     * Checks if 'this.customFrameRateChckBx' is checked;
                     * If it is, it checks to see if the Controls of 'this.videoTblLytPnl' contains 'this._frameRateCmbBx'
                     * If it does contain it, it assigns that Control to 'control', so it can then be removed.
                     * 
                     * If 'this.customFrameRateChckBx' is not checked;
                     * It checks to see if the Controls of 'this.videoTblLyPnl' contains 'this._customFrameRateUpDwn'
                     * If it does contain it, it assisns that Control to 'control', so it can then be removed.
                     */
                    if (
                        this.videoTblLytPnl.Controls.Contains(
                                                              control =
                                                              checkBox.Checked
                                                                  ? this._frameRateCmbBx as Control
                                                                  : this._customFrameRateUpDwn)) {
                                                                      this.videoTblLytPnl.Controls.Remove(control);
                                                                  }

                    this.videoTblLytPnl.Controls.Add(
                                                     checkBox.Checked
                                                         ? this._customFrameRateUpDwn as Control
                                                         : this._frameRateCmbBx,
                                                     1,
                                                     1);
                    break;
                }

                // Braces are used to allow the use of field 'control' more than once.
                case RecordAudioChckBx:
                case RecordMicrophoneChckBx:
                case RecordSystemAudioChckBx:
                {
                    var tuple = this._checkBoxToControlsAndMenuItems[checkBox];
                    var controls = tuple.Item1;
                    var menuItem = tuple.Item2;

                    menuItem.Checked = checkBox.Checked;

                    if (((RaiseEventEventArgs)eventArgs).Raise) {
                        this.MainMenuSubMenuItemHandler(menuItem, RaiseEventEventArgs.Forbid);
                    }

                    if (controls.Length > 1)
                    {
                        foreach (var control in controls) { control.Enabled = checkBox.Checked; }
                    }
                    else
                    { controls.First().Enabled = checkBox.Checked; }

                    break;
                }
            }
        }

我订阅它们的方式如下.

The way I am subscribing to them is as follows.

            this.customFrameRateChckBx.CheckedChanged += this.CheckBoxHandler;
            this.recordAudioChckBx.CheckedChanged += this.CheckBoxHandler;
            this.recordMicrophoneChckBx.CheckedChanged += this.CheckBoxHandler;
            this.recordSystemAudioChckBx.CheckedChanged += this.CheckBoxHandler;

            this.recordAudioSbMnTm.Click += this.MainMenuSubMenuItemHandler;
            this.recordMicrophoneSubMnTm.Click += this.MainMenuSubMenuItemHandler;
            this.recordSystemAudioSubMnTm.Click += this.MainMenuSubMenuItemHandler;

在构造函数的最后,我有了这个,它基本上触发了我需要触发的事件.

Right at the end of the constructor I have this which basically triggers the events that I need to be, triggered.

            this.CheckBoxHandler(this.customFrameRateChckBx, RaiseEventEventArgs.Allow);

创建我自己的事件的原因是因为我需要以某种方式告诉应用程序不要引发事件以及何时引发事件,这样我才不会最终陷入递归循环中.  我遇到问题的部分是代码所在的地方.  (无法 投放)

The reason why I have created my own Event is because I need to somehow tell the application not to raise events and when to raise events so I do not end up in a recursive loop.  The part I'm having the issues at are where it has the code.  (Unable to Cast)

                    if (((RaiseEventEventArgs)eventArgs).Raise) {
                        this.MainMenuSubMenuItemHandler(menuItem, RaiseEventEventArgs.Forbid);
                    }

if (((RaiseEventEventArgs)eventArgs).Raise) {
                        this.CheckBoxHandler(checkBox, RaiseEventEventArgs.Forbid);
                    }

之所以要检查天气还是不提出该事件,是因为如果不这样做,它将导致递归循环.

The reason why I am checking weather or not to raise the event is because if I don't it ends up in a recursive loop.

这里是全班为您提供更多信息的地方.记下字典,它们就是我正在使用的字典,因此我可以禁用/启用和选中/取消选中界面上的写入组件.

Here is the whole class to provide you with more information.  Take note of the Dictionaries, they are what I'm using so I can Disabled/Enable and Check/UnCheck the write components on the Interface.

namespace FrancescoMagliocco.FMScreenRecorder.Core.Forms
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Drawing;
    using System.Linq;
    using System.Windows.Forms;

    using Events;

    using Properties;

    public partial class MainForm : Form
    {
        private readonly ComboBox _frameRateCmbBx;

        private readonly Dictionary<CheckBox, Tuple<Control[], MenuItem>> _checkBoxToControlsAndMenuItems;
        private readonly Dictionary<MenuItem, Tuple<MenuItem[], CheckBox>> _menuItemToMenuItemsAndCheckBoxs;

        private readonly NumericUpDown _customFrameRateUpDwn;

        private const string CustomFrameRateChckBx = "customFrameRateChckBx";
        private const string RecordAudioChckBx = "recordAudioChckBx";
        private const string RecordMicrophoneChckBx = "recordMicrohphoneChckBx";
        private const string RecordSystemAudioChckBx = "recordSystemAudioChckBx";

        private const string CustomFrameRateSbMnTm = "customFrameRateSbMnTm";
        private const string RecordAudioSbMnTm = "recordAudioSbMnTm";
        private const string RecordMicrophoneSbMnTm = "recordMicrophoneSbMnTm";
        private const string RecordSystemAudioSbMnTm = "recordSystemAudioSbMnTm";

        private const string ConfigMicrophoneCodecSbMnTm = "configMicrophoneCodecSbMnTm";
        private const string ConfigSystemAudioCodecSbMnTm = "configSystemAudioCodecSbMnTm";

        private const string AboutFMScreenRecorder = "aboutFMScreenRecorderSbMnTm";
        private const string AboutFFmpeg = "aboutFFmpegSbMnTm";

        public MainForm()
        {
            this.InitializeComponent();

            this.customFrameRateChckBx.Name = CustomFrameRateChckBx;
            this.recordAudioChckBx.Name = RecordAudioChckBx;
            this.recordMicrophoneChckBx.Name = RecordMicrophoneChckBx;
            this.recordSystemAudioChckBx.Name = RecordSystemAudioChckBx;

            this.recordAudioSbMnTm.Name = RecordAudioSbMnTm;
            this.recordMicrophoneSubMnTm.Name = RecordMicrophoneSbMnTm;
            this.recordSystemAudioSubMnTm.Name = RecordSystemAudioSbMnTm;

            this.configMicrophoneCodecSbMnTm.Name = ConfigMicrophoneCodecSbMnTm;
            this.configSystemAudioCodecSbMnTm.Name = ConfigSystemAudioCodecSbMnTm;

            this.aboutFMScreenRecorderSbMnTm.Name = AboutFMScreenRecorder;
            this.aboutFFmpegSbMnTm.Name = AboutFFmpeg;

            this._frameRateCmbBx = new ComboBox
                                   {
                                       Dock = DockStyle.Fill,
                                       DropDownStyle = ComboBoxStyle.DropDownList,
                                       Items = {
                                                   "5",
                                                   "10",
                                                   "15",
                                                   "20",
                                                   "23.976",
                                                   "24",
                                                   "25",
                                                   "29.97",
                                                   "30",
                                                   "48",
                                                   "50",
                                                   "59.97",
                                                   "60",
                                                   "90",
                                                   "100",
                                                   "119.88",
                                                   "120",
                                                   "144",
                                                   "240"
                                               },
                                       Name = "frameRateChckBx",
                                       SelectedIndex = Settings.Default.FrameRateIndex
                                   };
            this._frameRateCmbBx.Font = new Font(this._frameRateCmbBx.Font, FontStyle.Regular);

            this._customFrameRateUpDwn = new NumericUpDown
                                         {
                                             DecimalPlaces = 3,
                                             Dock = DockStyle.Fill,
                                             Increment = .01M,
                                             Maximum = 999.999M,
                                             Minimum = 1M,
                                             Name = "customFrameRateUpDwn",
                                             Value = Settings.Default.CustomFrameRate
                                         };
            this._customFrameRateUpDwn.Font = new Font(this._customFrameRateUpDwn.Font, FontStyle.Regular);

            this._checkBoxToControlsAndMenuItems = new Dictionary<CheckBox, Tuple<Control[], MenuItem>>
                                                   {
                                                       {
                                                           this.recordAudioChckBx,
                                                           new Tuple<Control[], MenuItem>(
                                                           new Control[]
                                                           { this.microphoneGrpBx, this.systemAudioGrpBx },
                                                           this.recordAudioSbMnTm)
                                                       },
                                                       {
                                                           this.recordMicrophoneChckBx,
                                                           new Tuple<Control[], MenuItem>(
                                                           new Control[] { this.microphoneGrpBx },
                                                           this.recordMicrophoneSubMnTm)
                                                       },
                                                       {
                                                           this.recordSystemAudioChckBx,
                                                           new Tuple<Control[], MenuItem>(
                                                           new Control[] { this.systemAudioGrpBx },
                                                           this.recordSystemAudioSubMnTm)
                                                       }
                                                   };

            this._menuItemToMenuItemsAndCheckBoxs = new Dictionary<MenuItem, Tuple<MenuItem[], CheckBox>>()
                                                    {
                                                        {
                                                            this.recordAudioSbMnTm,
                                                            new Tuple<MenuItem[], CheckBox>(
                                                            new[]
                                                            {
                                                                this.recordMicrophoneSubMnTm,
                                                                this.recordSystemAudioSubMnTm,
                                                                this.configureSbMnTm
                                                            },
                                                            this.recordAudioChckBx)
                                                        },
                                                        {
                                                            this.recordMicrophoneSubMnTm,
                                                            new Tuple<MenuItem[], CheckBox>(
                                                            new[] { this.configMicrophoneCodecSbMnTm },
                                                            this.recordMicrophoneChckBx)
                                                        },
                                                        {
                                                            this.recordSystemAudioSubMnTm,
                                                            new Tuple<MenuItem[], CheckBox>(
                                                            new[] { this.configSystemAudioCodecSbMnTm },
                                                            this.recordSystemAudioChckBx)
                                                        }
                                                    };

            this.customFrameRateChckBx.CheckedChanged += this.CheckBoxHandler;
            this.recordAudioChckBx.CheckedChanged += this.CheckBoxHandler;
            this.recordMicrophoneChckBx.CheckedChanged += this.CheckBoxHandler;
            this.recordSystemAudioChckBx.CheckedChanged += this.CheckBoxHandler;

            this.regionCmbBx.SelectedIndexChanged += this.ComboBoxHandler;

            this.recordAudioSbMnTm.Click += this.MainMenuSubMenuItemHandler;
            this.recordMicrophoneSubMnTm.Click += this.MainMenuSubMenuItemHandler;
            this.recordSystemAudioSubMnTm.Click += this.MainMenuSubMenuItemHandler;

            this.customFrameRateChckBx.Checked = Settings.Default.UseCustomFrameRate;
            this.recordAudioSbMnTm.Checked = this.recordAudioChckBx.Checked = Settings.Default.RecordAudio;
            this.recordMicrophoneSubMnTm.Checked = this.recordMicrophoneChckBx.Checked = Settings.Default.RecordMicrophone;
            this.recordSystemAudioSubMnTm.Checked = this.recordSystemAudioChckBx.Checked = Settings.Default.RecordSystemAudio;

            this.regionCmbBx.SelectedIndex = Settings.Default.RegionIndex;

            this.CheckBoxHandler(this.customFrameRateChckBx, RaiseEventEventArgs.Allow);
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Form.Closing"/> event.
        /// </summary>
        /// <param name="e">A <see cref="T:System.ComponentModel.CancelEventArgs"/> that contains the event data. </param>
        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);

            Settings.Default.RecordMicrophone = this.recordMicrophoneChckBx.Checked;
            Settings.Default.CustomFrameRate = this._customFrameRateUpDwn.Value;
            Settings.Default.FrameRateIndex = this._frameRateCmbBx.SelectedIndex;
            Settings.Default.RecordAudio = this.recordAudioChckBx.Checked;
            Settings.Default.RecordSystemAudio = this.recordSystemAudioChckBx.Checked;
            Settings.Default.RegionIndex = this.regionCmbBx.SelectedIndex;
            Settings.Default.UseCustomFrameRate = this.customFrameRateChckBx.Checked;
            Settings.Default.MicrphoneIndex = this.micrphoneCmbBx.SelectedIndex;
            Settings.Default.Save();
        }

        private void CheckBoxHandler(object sender, EventArgs eventArgs)
        {
            var checkBox = sender as CheckBox;

            switch (checkBox?.Name)
            {

                // Braces are used to allow the use of field 'control' more than once.
                case CustomFrameRateChckBx:
                {
                        Control control;

                    /*
                     * Checks if 'this.customFrameRateChckBx' is checked;
                     * If it is, it checks to see if the Controls of 'this.videoTblLytPnl' contains 'this._frameRateCmbBx'
                     * If it does contain it, it assigns that Control to 'control', so it can then be removed.
                     * 
                     * If 'this.customFrameRateChckBx' is not checked;
                     * It checks to see if the Controls of 'this.videoTblLyPnl' contains 'this._customFrameRateUpDwn'
                     * If it does contain it, it assisns that Control to 'control', so it can then be removed.
                     */
                    if (
                        this.videoTblLytPnl.Controls.Contains(
                                                              control =
                                                              checkBox.Checked
                                                                  ? this._frameRateCmbBx as Control
                                                                  : this._customFrameRateUpDwn)) {
                                                                      this.videoTblLytPnl.Controls.Remove(control);
                                                                  }

                    this.videoTblLytPnl.Controls.Add(
                                                     checkBox.Checked
                                                         ? this._customFrameRateUpDwn as Control
                                                         : this._frameRateCmbBx,
                                                     1,
                                                     1);
                    break;
                }

                // Braces are used to allow the use of field 'control' more than once.
                case RecordAudioChckBx:
                case RecordMicrophoneChckBx:
                case RecordSystemAudioChckBx:
                {
                    var tuple = this._checkBoxToControlsAndMenuItems[checkBox];
                    var controls = tuple.Item1;
                    var menuItem = tuple.Item2;

                    menuItem.Checked = checkBox.Checked;

                    if (((RaiseEventEventArgs)eventArgs).Raise) {
                        this.MainMenuSubMenuItemHandler(menuItem, RaiseEventEventArgs.Forbid);
                    }

                    if (controls.Length > 1)
                    {
                        foreach (var control in controls) { control.Enabled = checkBox.Checked; }
                    }
                    else
                    { controls.First().Enabled = checkBox.Checked; }

                    break;
                }
            }
        }

        private void ComboBoxHandler(object sender, EventArgs eventArgs)
        {
            
        }

        private void MainMenuSubMenuItemHandler(object sender, EventArgs eventArgs)
        {
            var menuItem = sender as MenuItem;
            var menuItemName = menuItem?.Name;


            if (menuItemName == this.closeSbMnTm.Name)
            {
#warning This may not allow the 'OnClosing' event to be triggered, therefore not allowing the settings to be updated.
                Application.ExitThread();
                return;
            }

            switch (menuItemName)
            {
                case RecordAudioSbMnTm:
                case RecordMicrophoneSbMnTm:
                case RecordSystemAudioSbMnTm:
                    var tuple = this._menuItemToMenuItemsAndCheckBoxs[menuItem];
                    var menuItems = tuple.Item1;
                    var checkBox = tuple.Item2;

                    /*
                     * Checks not only if the menuItem is checked, but is also changes its checked state if it's Enabled.
                     * Alreach checked if explicit check for it being Enabled was needed, and it's not.
                     */
                    var isChecked = menuItem.Checked = checkBox.Checked = !menuItem.Checked;

                    if (((RaiseEventEventArgs)eventArgs).Raise) {
                        this.CheckBoxHandler(checkBox, RaiseEventEventArgs.Forbid);
                    }

                    if (menuItems.Length > 1)
                    {
                        /*
                         * This part will only be reached (So far) if the case is 'RecordAudioSbMnTm', and will only set the
                         * 'RecordMicrophoneSbMnTm' and 'RecordSystemAudioSbMnTm' to be Enabled based on 'isChecked',
                         * it will also set the 'this.configureSbMnTm' Enabled state based on 'isChecked' as well, but NOT
                         * the 'this.configMicrophoneCodecSbMnTm' or 'this.configSystemAudioCodecSbMnTm' Enabled states.
                         */
                        foreach (var subMenuItem in menuItems) { subMenuItem.Enabled = isChecked; }
                    }
                    else
                    { menuItems.First().Enabled = isChecked; }

                    break;
                case ConfigMicrophoneCodecSbMnTm:
                case ConfigSystemAudioCodecSbMnTm:
                    break;
            }
        }
    }
}


推荐答案

这是很多代码,所以我不确定我是否了解所有细节.我将为您提供通常的事件设计步骤.

That is a lot of code, so I am not sure I get all the details. I will give you the usual event design steps.

每个事件都基于一个委托.委托是大多数其他C样式语言中裸函数指针的替代.

Every event is based on a Delegate. Delegates are replacements for naked function pointers in most other C-style langauges.

委托(以及任何处理程序)的惯用签名是:
(对象发送者,EventArgs e)
如果需要处理更多内容,请编写适当的EventArgs派生类并使用它代替签名中的基本类.

The customary signature for the delegate (and thus any handler) is:
(object sender, EventArgs e)
If you need more stuff to be handed in, write a proper EventArgs derived class and use it instead of the basic class in the signature.

使用事件代码字可以使外部代码只能在变量中添加或删除(如get和set这样的公共添加和删除).但是您仍然具有直接从类代码访问变量的能力,例如必须"null"或"null".所有事件 处置.

The event codeword makes it so that external code can only add or remove to the variable (public add and remove like get and set). But you still have direct ability to acces the variable from class code, like when having to "null" all events on disposing.

习惯上,从不直接从任何函数引发事件,而是编写受保护的"RaiseEvent".功能.
这样,继承者可以在提高调用的同时添加自定义处理,同时仍然调用所有基本代码.它还避免了代码的重复.

It is also customary to never raise the event directly from any function, but write a protected "RaiseEvent" function.
That way inheritors can add thier custom handling to the raising while still calling all basic code. It also avoids repetition of code.

这是更全面的指南:
https://msdn.microsoft.com/en-us/library/aa645739.aspx

Here is a more comprehensive toutorial:
https://msdn.microsoft.com/en-us/library/aa645739.aspx


这篇关于通过处理程序传递自定义EventArgs的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆