让 2 个彼此一无所知的类在 C# 中共享事件?
我有三个类,其中一个类将配置文件加载到内存中以供稍后访问。我的另一个类是主窗体。我试图实现的是,当加载配置类的某些元素时,它们将被添加到 GUI (WindowsForm) 中的列表视图中。
我知道你无法直接从其他非主窗体类访问 GUI,读完后我无论如何也不想这样做,所以我一直在尝试触发事件来表示主窗体将侦听的“配置已更新”并在适当的时候更新列表视图。因此,我创建了第三个类来定义事件和委托等,但在我看到的所有示例中,如果不同的类调用事件,它们都会传递事件类的共享实例。
这是我应该做的事情吗?当我从主窗体类创建配置类时,我应该传递事件类的实例吗?或者有没有办法让两个互不了解的班级共享一个活动?
我修改了下面的微软示例来半演示我所需要的内容。
using System;
public class FireEventArgs : EventArgs
{
public FireEventArgs(string room, int ferocity)
{
this.room = room;
this.ferocity = ferocity;
}
public string room;
public int ferocity;
}
public class FireAlarm
{
public delegate void FireEventHandler(object sender, FireEventArgs fe);
public event FireEventHandler FireEvent;
public void ActivateFireAlarm(string room, int ferocity)
{
FireEventArgs fireArgs = new FireEventArgs(room, ferocity);
if(FireEvent!=null)FireEvent(this, fireArgs);
}
}
public class FireEventTest
{
public static void ExtinguishFire(object sender, FireEventArgs fe)
{
Console.WriteLine("\nThe ExtinguishFire function was called by {0}.", sender.ToString());
if (fe.ferocity < 2)
Console.WriteLine("This fire in the {0} is no problem. I'm going to pour some water on it.", fe.room);
else if (fe.ferocity < 5)
Console.WriteLine("I'm using FireExtinguisher to put out the fire in the {0}.", fe.room);
else
Console.WriteLine("The fire in the {0} is out of control. I'm calling the fire department!", fe.room);
}
public static void Main()
{
FireAlarm myFireAlarm = new FireAlarm();
FireAlarm fireAlarm = new FireAlarm();
fireAlarm.FireEvent += new FireAlarm.FireEventHandler(ExtinguishFire);
myFireAlarm.ActivateFireAlarm("Kitchen", 3);
myFireAlarm.ActivateFireAlarm("Study", 1);
myFireAlarm.ActivateFireAlarm("Porch", 5);
return;
}
}
预先感谢您的任何帮助。
I have three classes, one class loads in a configuration file into memory for access later on. My other class is the mainform. What I am attempting to achieve is that when certain elements of the configuration class are loaded in they are added to a listview in the GUI (WindowsForm).
I know you can't access the GUI directly from the other non-mainform classes, which after reading I don't want to do anyway, so I have been attempting to fire events to say "config updated" that the mainform will listen for and update the listview when appropriate. So I created a third class that defines the events and the delegates etc but in all the examples I've seen if different classes are calling the event they are all passed a shared instance of the event class.
Is this the way I should do things? When I created the configuration class from the mainform class should I pass an instance of the event class? Or is there a way for 2 classes that don't know anything about each other to share an event?
I've modified a microsoft example below to semi demonstrate what I'm needing.
using System;
public class FireEventArgs : EventArgs
{
public FireEventArgs(string room, int ferocity)
{
this.room = room;
this.ferocity = ferocity;
}
public string room;
public int ferocity;
}
public class FireAlarm
{
public delegate void FireEventHandler(object sender, FireEventArgs fe);
public event FireEventHandler FireEvent;
public void ActivateFireAlarm(string room, int ferocity)
{
FireEventArgs fireArgs = new FireEventArgs(room, ferocity);
if(FireEvent!=null)FireEvent(this, fireArgs);
}
}
public class FireEventTest
{
public static void ExtinguishFire(object sender, FireEventArgs fe)
{
Console.WriteLine("\nThe ExtinguishFire function was called by {0}.", sender.ToString());
if (fe.ferocity < 2)
Console.WriteLine("This fire in the {0} is no problem. I'm going to pour some water on it.", fe.room);
else if (fe.ferocity < 5)
Console.WriteLine("I'm using FireExtinguisher to put out the fire in the {0}.", fe.room);
else
Console.WriteLine("The fire in the {0} is out of control. I'm calling the fire department!", fe.room);
}
public static void Main()
{
FireAlarm myFireAlarm = new FireAlarm();
FireAlarm fireAlarm = new FireAlarm();
fireAlarm.FireEvent += new FireAlarm.FireEventHandler(ExtinguishFire);
myFireAlarm.ActivateFireAlarm("Kitchen", 3);
myFireAlarm.ActivateFireAlarm("Study", 1);
myFireAlarm.ActivateFireAlarm("Porch", 5);
return;
}
}
Thanks in advance for any help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
好吧,我不认为我完全理解你,但是你可以有一个名为 EventDispatcher 的类,如果你愿意的话,将其设置为 Singleton,并在其中有一个公共事件
ConfigurationElementLoaded(object sender, ConfigurationElementLoadedArgs args)
以及触发事件的公共方法:
您可以在其中触发事件。
您的 mainForm 可以通过 Singleton 实例进行订阅:
EventDispatcher.Instance.ConfigurationElementLoaded += ...
并且您的配置可以使用
FireConfigurationElementLoaded
触发事件。如果这个答案没有帮助,请详细说明您到底想做什么......
Well, I don't think that I understand you fully, but you can have a class called EventDispatcher, make it Singleton if you want, and inside it have a public event
ConfigurationElementLoaded(object sender, ConfigurationElementLoadedArgs args)
and a public method to fire the event:
in which you fire the event.
Your mainForm can subscribe via the Singleton isntance :
EventDispatcher.Instance.ConfigurationElementLoaded += ...
and your Configuration can fire the event with
FireConfigurationElementLoaded
.If this answer doesn't help, please elaborate more what exactly you want to do...
嗯,如果这些类对彼此一无所知,我认为这会有点混乱,但事实并非如此,对吧? UI 知道它想要监听什么事件。
不过这绝对没问题,ui 绝对可以知道它应该显示什么,至少通过界面。您不希望业务类依赖于 UI(您需要单向依赖流)
我想说,要么定义一个包含事件的接口并在 FireAlarm 中实现它,要么直接监听
FireAlarm
中的事件。另外,严格来说,情况并非如此,表单外部的代码不能在表单内部使用。 ui 绝对可以通过您编写的自定义 EventArgs(包括
sender
对象)侦听和使用事件。真正重要的是哪个线程正在运行相关代码。只要从 UI 线程(创建 ui 的线程)访问 UI,您就可以运行任何代码。
您发布的代码不起作用有什么原因吗?
Hm, if the classes know nothing about each other at all i think it will be a little messy, but thats not really the case though right? The UI knows what event it wants to listen to.
This is absolutley fine though, ui can absolutly know about what its supposed to display, atleast via an interface. What you dont want is to have the business classes be dependant on the UI (you want an unidirectional flow of dependencies)
I would say either define an interface containing your events and implement it in
FireAlarm
or listen directly to the events inFireAlarm
.Also, its strictly speaking not the case the code outside the form cant be used inside the the form. its absolutley fine for the ui to listen to and use an event with a custom EventArgs written by you, including the
sender
object.What really matter is what thread is running the code in question. As long as the UI is accessed from the UI thread (the thread that created the ui) you can run any code.
Is there a reason why the code you've posted doesnt work?
如果您只想更新 Windows 窗体 UI 上的内容,请在控件上使用数据绑定。
创建一个数据层,其中包含配置文件的信息并将其属性绑定到界面控件。当您更改该属性的值时,数据绑定机制将关心更新您的 UI。
一般来说,我的观点是:如果您使用的框架中已经存在某些内容
(在本例中是.NET框架)适合您的需求,只需使用它,不要发明自行车,因为其他人已经在发明它时遭受了痛苦:)
WindowsForm 的数据绑定示例
看着所有这些事件,我认为我们正在谈论 WindowsForm 应用程序。如果没有,请精确。
希望这有帮助。
Use a databindind on controls if you just want to update a content on UI of your windows form.
Create a data layer which holds an inormation of your config file and bind its properties to your interface controls. At the moment you change values of that properties databinding mechanism will care about updating your UI.
In genareal my opinion is: if something already exist in framework you use
(in this case .NET framework) that fits your needs, just use it, do not invent bycicle, cause someone else already suffered inventing it :)
DataBinding for WindowsForm example
Looking at all that events stuff I presumed that we are talking about WindowsForm application. If not, please precise.
Hope this helps.