c# 从另一个类中的另一个静态事件引发事件

2024-05-21

需要帮助从另一个班级调用事件。 我有已声明事件的课程:

     public class MxPBaseGridView : GridView
    {

        public event AddNewItemsToPopUpMenuEventHandler AddNewItemsToPopUpMenu;
          ...
    }

我需要调用事件的另一个类具有方法和“AddNewItemsToPopUpMenuEventHandler”委托

    public delegate void AddNewItemsToPopUpMenuEventHandler(PopupMenuShowingEventArgs e);
    public static class GridViewUtils
{
public static void gridView_PopupMenuShowing(object sender, PopupMenuShowingEventArgs e)
    {                     
        if (e.MenuType != DevExpress.XtraGrid.Views.Grid.GridMenuType.Row)
        {
           if (menu != null)
            {               
                if (sender is MxPBaseAdvBandedGridView)
                {
                    MxPBaseAdvBandedGridView currentGrid = sender as MxPBaseAdvBandedGridView;

...

                    currentGrid.AddNewItemsToPopUpMenu();
                    if (currentGrid.AddNewItemsToPopUpMenu != null) //there i need to call event
                        currentGrid.AddNewItemsToPopUpMenu(e); // how you understand it doesn't work 
                }

那么做同样的工作的正确方法是什么?


C# 中的事件是一些有趣的事情。它们非常类似于自动属性,但具有私有 get 方法和公共(或您选择的任何访问权限)set 方法。

请允许我演示一下。让我们创建一个包含假设事件的假设类。

class SomeObject{
    public event EventHandler SomeEvent;

    public void DoSomeStuff(){
        OnSomeEvent(EventArgs.Empty);
    )

    protected virtual void OnSomeEvent(EventArgs e){
        var handler = SomeEvent;
        if(handler != null)
            handler(this, e);
    }
}

此类遵循公开事件的类的典型模式。它公开公开该事件,但有一个受保护的虚拟“On...”方法,默认情况下,该方法仅调用该事件(如果它有任何订​​阅者)。这个受保护的虚方法不仅封装了实际调用事件的逻辑,而且为派生类提供了一种方法:

  • 以更少的开销方便地处理事件,
  • 在所有外部订阅者收到事件之前或之后执行一些处理,
  • 调用一个完全不同的事件,或者
  • 完全压制该事件。

但是这个名为 SomeEvent 的“事件”对象是什么?在 C# 中,我们熟悉字段、属性和方法,但事件到底是什么?

在我们开始讨论之前,认识一下 C# 中实际上只有两种类型的类成员:字段和方法。属性和事件或多或少只是它们之上的语法糖。

属性实际上是一种或两种方法,以及存储在元数据中的名称,C# 编译器允许您使用该名称来引用这两种方法之一。也就是说,当您定义这样的属性时:

public string SomeProperty{
    get{return "I like pie!";}
    set{
        if(string.Compare(value, "pie", StringComparison.OrdinalIgnoreCase) == 0)
            Console.WriteLine("Pie is yummy!");
        else Console.WriteLine("\"{0}\" isn't pie!", value ?? "<null>");
    }
}

编译器为你编写了两个方法:

public string get_SomeProperty(){return "I like pie!";}
public void   set_SomeProperty(string value){
    if(string.Compare(value, "pie", StringComparison.OrdinalIgnoreCase) == 0)
        Console.WriteLine("Pie is yummy!");
    else Console.WriteLine("\"{0}\" isn't pie!", value ?? "<null>");
}

我并不是间接地表达这个意思。这两个方法实际上成为编译类的一部分,以及有关属性的大量元数据,它告诉编译器下次在读取(获取)或写入(设置)属性时要调用哪些方法。所以当你写这样的代码时:

var foo = someObject.SomeProperty;
someObject.SomeProperty = foo;

编译器找到分配给的 getter 和 setter 方法SomeProperty,并将您的代码变成:

string foo = someObject.get_SomeProperty();
someObject.set_SomeProperty(foo);

这就是为什么如果您定义一个具有公共字段的类,但后来决定将其更改为属性,以便在读取或写入该类时可以做一些有趣的事情,则必须重新编译包含对此的引用的任何外部程序集成员,因为字段访问指令需要改为方法调用指令。

现在这个属性有些反常,不依赖任何后盾。它的 getter 返回一个常量值,并且它的 setter 没有将其值存储在任何地方。需要明确的是,这是完全有效的,但大多数时候,我们定义的属性更像是这样的:

string someProperty;

public string SomeProperty{get{return someProperty;}set{someProperty = value;}}

除了读取和写入字段之外,此属性不执行任何操作。它与名为的公共字段几乎相同SomeProperty,除了你could稍后向该 getter 和 setter 添加逻辑,而不会使您的类的使用者重新编译。但这种模式非常常见,以至于 C# 3 添加了“自动属性”来达到相同的效果:

public string SomeProperty{get;set;}

编译器将其转换为与我们上面编写的代码相同的代码,只是支持字段有一个只有编译器知道的超级秘密名称,因此我们只能在代码中引用该属性,即使在类本身中也是如此。

因为我们无法访问支持字段,而您可能具有如下所示的只读属性:

string someProperty;

public string SomeProperty{get{return someProperty;}}

你几乎永远不会看到只读自动属性(编译器允许你编写它们,但你会发现它们很少用):

public string SomeProperty{get;} // legal, but not very useful unless you always want SomeProperty to be null

相反,您通常会看到这样的内容:

public string SomeProperty{get;private set;}

The private访问修饰符附加到set使得类内的方法可以设置属性,但该属性在类外仍然显示为只读。

“现在这和事件有什么关系呢?”你可能会问。事实上,事件非常类似于自动属性。通常,当您声明事件时,编译器会生成一个超级秘密支持字段和一对方法。除了支持字段并不是那么超级秘密,并且这对方法不是“获取”和“设置”,而是“添加”和“删除”。让我演示一下。

当你写一个这样的事件时:

public event EventHandler SomeEvent;

编译器写的是这样的:

EventHandler SomeEvent;

public void add_SomeEvent(EventHandler value){
    SomeEvent = (EventHandler)Delegate.Combine(SomeEvent, value);
}
public void remove_SomeEvent(EventHandler value){
    SomeEvent = (EventHandler)Delegate.Remove(SomeEvent, value);
}

它还添加了一些元数据粘合,以便稍后,当您编写如下代码时:

void Awe_SomeEventHandler(object sender, EventArgs e){}

void SomeMethod(SomeObject Awe){
    Awe.SomeEvent += Awe_SomeEventHandler
    Awe.SomeEvent -= Awe_SomeEventHandler
}

编译器将其重写为(仅有趣的行):

Awe.add_SomeEvent(Awe_SomeEventHandler);
Awe.remove_SomeEvent(Awe_SomeEventHandler);

这里需要注意的是,唯一可公开访问的成员与SomeEvent是那些添加和删除方法,当您使用+= and -=运营商。支持字段(名为 SomeEvent 的委托对象,保存事件的订阅者)是一个私有字段,只有声明类的成员才能访问。

然而,就像自动属性只是手动编写支持字段以及 getter 和 setter 的快捷方式一样,您也可以显式声明委托并添加和删除方法:

internal EventHandler someEvent;

public event EventHandler SomeEvent{
    add{someEvent = (EventHandler)Delegate.Combine(someEvent, value);}
    remove{someEvent = (EventHandler)Delegate.Remove(someEvent, value);}
}

然后,程序集中的其他类可以触发您的事件:

var handler = Awe.someEvent;
if(handler != null)
    handler(Awe, EventArgs.Empty);

然而,以正常(自动)方式定义事件更简单、更惯用,只需公开“Raise”方法即可:

internal void RaiseSomeEvent(){OnSomeEvent(EventArgs.Empty);}

但现在你希望明白why你必须这样做,并且后台发生了什么。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c# 从另一个类中的另一个静态事件引发事件 的相关文章

随机推荐

  • 我应该使用排队系统来处理付款吗?

    我在用着Slim https www slimframework com和这个结合Stripe 的 PHP 库 https stripe com docs api php在我的应用程序中处理付款 一切都很好 但是直到最近 我在我的系统中发现
  • 是否可以从 C++ 应用程序调用 C# 应用程序?

    我是一名编程学生 现在我已经上了两门 C 课程 这个学期我将参加我的第一门 C 课程 出于好奇 是否可以从 C 应用程序调用 C 应用程序 如果是的话 是否还可以检查运行该程序的计算机是否具有 NET框架 我只是很好奇 我想如果可能的话 这
  • 带表达式的 F# 类型定义

    是否可以这样表达 type id int gt 0 我知道它不可能静态执行 因为这意味着 F 具有依赖类型 在 C 中 我习惯于使用代码契约来执行此类操作并获得运行时强制执行 我正在这里寻找类似的东西 Thanks 编辑 感谢您提供的所有答
  • Ctrl + Space 不适用于 Eclipse 上的内容辅助

    我的问题是点击后不会弹出内容辅助窗口Ctrl Space 我检查了我的快捷方式 内容辅助必然会Ctrl Space 有时 例如在输入点后 窗口会自动弹出提出建议 但使用组合键时不会发生这种情况 日食版本 面向 Web 开发人员的 Eclip
  • 将图像保存到内部存储器并将出现在图库中

    我搜索了很多与我的问题相关的问题 是否有办法将图像存储在内存中并且它也应该出现在图库中 这是完全有可能的 我以前也这么做过 在将图像保存到内存 或称为应用程序文件夹等 之前 您最好设置Context MODE WORLDREADABLE 虽
  • React Native Android:app:compileDebugJava 错误

    当我运行react native run android时 出现以下错误 我正在将其设置为在设备上运行 app compileDebugJava Users hello MediaFire apps test2 android app sr
  • Switch 语句,其中 value 为 Int 但 case 可以包含数组 [重复]

    这个问题在这里已经有答案了 我想将我的值数组作为 switch 语句的案例 我有一个值数组 let intValues 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 100 我想使用
  • SVG 转 JPG / PNG

    有没有工作模块可以convert a SVG image into像素格式如JPEG or PNG 看看蜡染工具包 具体来说是光栅化器 http xmlgraphics apache org batik tools rasterizer h
  • Mac OS X 中文件系统的 Unicode 编码在 Python 中不正确?

    在 OS X 和 Python 中处理 Unicode 文件名有点困难 我试图在代码中稍后使用文件名作为正则表达式的输入 但文件名中使用的编码似乎与 sys getfilesystemencoding 告诉我的不同 采取以下代码 usr b
  • Java - toString 到 Color

    我一整天都在努力解决这个问题 基本上我做了一个 for 循环 将条目添加到数组列表中 其中一项是 颜色 变量 我已经用过random nextInt为颜色构造函数的红色 绿色和蓝色部分创建新值 我还设置了一个toString方法 这样我就可
  • Java时间转正常格式

    我有 Java 时间1380822000000 我想转换为我可以阅读的内容 import java util Date object Ws1 val a new Date 1380822000000 toString 导致异常 warnin
  • Python 中的流式传输管道

    我正在尝试使用 Python 将 vmstat 的输出转换为 CSV 文件 因此我使用类似的方法转换为 CSV 并将日期和时间添加为列 vmstat 5 python myscript py gt gt vmstat log 我遇到的问题是
  • Azure Active Directory - 自定义策略错误

    我已按照此处提供的指南在 Azure AD B2C 中设置了自定义策略 https learn microsoft com azure active directory b2c active directory b2c setup sf a
  • 如何在 xcode 中使用相同的 nib 文件创建多个窗口

    我有一个使用表格视图作为界面的 iPhone 应用程序 每次用户点击其中一个表格单元格时 我想向用户显示另一个窗口 然而 我推入导航控制器的窗口的用户界面非常相似 因此 我决定制作一个 通用 nib 文件 以便在该通用 nib 文件的文件所
  • 从 iFrame 嵌入 API 获取 YouTube 视频信息

    我正在使用 YouTube iFrame API 嵌入视频并创建一个简单的自定义播放器 我正在寻找视频标题 描述 等 无需再次调用 YouTube 即可获取信息 我无法找到任何相关信息 有什么想法 或者我是否需要额外拨打电话来获取视频信息
  • 工作日重新订购 Pandas 系列

    使用 Pandas 我提取了一个 CSV 文件 然后创建了一系列数据来找出一周中哪几天崩溃最多 crashes by day bc DAY OF WEEK value counts 然后我将其绘制出来 但当然它按照与该系列相同的排名顺序绘制
  • 无法将 std::min 传递给函数,std::min 的副本有效

    Passing std min函数无法编译 我复制了 libcpp 声明std min进入我的源文件并且它可以工作 std 版本有什么问题 clang 和 gcc 也会发生同样的情况 在 Godbolt 上测试 https godbolt
  • Pinterest 拒绝来自 Google App Engine 的访问 (403)

    使用 oauth accessToken 我可以通过以下方式检索用户的信息 https api pinterest com v1 me fields first name 2Cid 2Clast name 2Curl 2Cusername
  • 使用 Hibernate Criteria 过滤 Map 中的键和值

    我有以下持久类 public class Code ElementCollection targetClass CodeValue class MapKeyClass CodeProperty class JoinTable name co
  • c# 从另一个类中的另一个静态事件引发事件

    需要帮助从另一个班级调用事件 我有已声明事件的课程 public class MxPBaseGridView GridView public event AddNewItemsToPopUpMenuEventHandler AddNewIt