让一个类'inform'需要更改的另一个类(Events?)
本文关键字:另一个 Events inform 一个 | 更新日期: 2023-09-27 18:18:35
好了,我一直在网站和谷歌上搜索,但我不太明白委派和事件处理程序之类的东西需要在哪里,所以希望这里有人能帮助/解释我需要做什么。
所以,我写一个简单的数据库应用程序(使用SQLite)。有一个主窗体,它是MDI父窗体(它基本上是一个顶部有菜单的大窗口)。菜单启动其他窗口,允许查看、编辑和插入数据库的各种表。
其中一个窗口是LOG窗口,它显示我的日志表。
目前,如果用户在显示TABLE中的数据的窗口中更改了某些内容。该操作还写入日志表。但是,如果日志窗口打开,则日志视图不会更新。
所以,我发现我可能需要从我的TABLE UPDATE代码中"触发"一个事件,我的LOG窗口"订阅"(所以它可以更新DataGridView)。
我不知道的是这个事件的不同"部分"去了哪里。
MdiParent应该有public delegate void EventHandler();
吗?如果不是,在哪里?
哪个类获得public static event EventHandler logGoneStale;
?
唯一的位我相当肯定的是,显示日志的窗口(它有一个方法称为公共无效UpdateLogDataGridView() -它调用数据库对象/方法(重新)填充datagridview)需要有:
里面有logGoneStale += new EventHandler(UpdateLogDataGridView);
之类的。这至少是对的吧?
完全困惑-似乎没有一个事件的例子/教程在MSDN试图做我想要实现的。
您需要在发送事件的类中定义一个event
,并在应该接收事件的类中附加一个事件处理程序。为了使事情简单一点,从c# 3.5开始,您可以完全忘记delegate
关键字,而使用lambda表达式作为事件处理程序。还要注意,在大多数情况下,将事件设置为static
是没有意义的,因为事件通常由实例触发,而不是由类触发。
的例子:
class SendsEvent
{
public event EventHandler MyEvent;
public void FireEvent()
{
if(MyEvent != null) // MyEvent is null if no handlers have been attached
{
MyEvent(this, new EventArgs()); // event fired here
}
}
}
class ReceivesEvent
{
private SendsEvent eventSource;
public ReceivesEvent(SendsEvent eventSource)
{
this.eventSource = eventSource;
// Attach event handler - can be a lambda expression
// or method with signature
// "void HandleEvent(object sender, EventArgs e)"
this.eventSource.MyEvent += (sender, args) =>
{
// do something when event was fired
Console.Out.WriteLine("Hello. Event was fired.");
};
}
}
class Program
{
public static void Main()
{
var eventSource = new SendsEvent();
var eventReceiver = new ReceivesEvent(eventSource);
eventSource.FireEvent();
}
}
处理事件需要同时拥有事件发布者和事件订阅者。
@chris' s 答案是正确的
此外,您需要在您想要通知的操作发生的最近点上引发事件。
例如,实现INotifyPropertyChanged接口
public class Customer : INotifyPropertyChanged {
public string Name { get; set; }
public string Address {
get { return address; }
set {
address = value;
if (thereArePropertyChangedEventSubcribers())
raisePropertyChangedEventFor("Address");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void raisePropertyChangedEventFor(string propertyName) {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private bool thereArePropertyChangedEventSubcribers() {
return PropertyChanged != null;
}
private string address;
}
所以这里,Customer
类允许发布它的地址更改。因此,每当有人对地址更改时的通知感兴趣时,它就像这样订阅事件:
Customer.PropertyChanged += new PropertyChangedEventHandler(customerPropertyChanged);
或者像这样:
Customer.PropertyChanged += customerPropertyChanged;
你甚至可能已经注意到,地址最近的改变点是在它实际改变后直接发生的。唯一的要求是用作事件处理程序的方法具有与事件本身相同的签名。如果您看一下PropertyChangedEventHandler委托,您可能会注意到它的签名等待一个object
作为第一个参数,即触发事件的对象,以及一个PropertyChangedEventArgs实例来通知已更改的属性。
回到您的示例,您希望无论何时将日志插入到底层数据库中,都能被注意到,以便可能出现log窗口的刷新。当你想要使用事件时,有两个问题需要回答。
- 我的出版商应该是什么?
- 我的订户应该是什么?
我的出版商应该是什么?
MdiParent应该有
public delegate void EventHandler();
吗?
简短的回答:不!
If not where?
事件声明最适合发布者。如果您有一个负责日志记录的类,那么public delegate void EventHandler();
应该驻留在这里,因为它负责在有订阅者时引发事件。
每当成功插入一条日志时,它应通知任何有兴趣知道新日志条目的订阅者。
public class Log {
public void UpdateLog(string description) {
// insert the new Log line into your database.
if (thereIsAtLeastOneNewLogEntryAddedSubscriber())
raiseTheNewLogEntryAddedEvent();
}
public event EventHandler NewLogEntryAdded;
private raiseTheNewLogEntryAddedEvent() {
NewLogEntryAdded(this, EventArgs.Empty);
}
private bool thereIsAtLeastOneNewLogEntryAddedSubscriber() {
return NewLogEntryAdded != null;
}
}
我的订户应该是什么?
这个问题可以通过另一个问题来回答:
- 当事件触发时,您需要做什么?
在您的案例中,您希望在打开日志窗口时更新日志窗口。
我唯一可以合理确定的是,显示日志的窗口(它有一个名为public void UpdateLogDataGridView()的方法-它调用数据库对象/方法(重新)填充datagridview)需要有:
里面有
logGoneStale += new EventHandler(UpdateLogDataGridView);
之类的东西。这至少是对的吧?
是的,你是对的!= D
您实际上订阅了每行的事件。因此,它告诉应用程序,显示日志的窗口有兴趣了解数据库中的日志更改。
public class WindowThatDisplaysTheLog : Form {
public WindowThatDisplaysTheLog() {
InitializeComponent();
log = new Log();
log.NewLogEntryAdded += UpdateLogDataGridView;
}
private void UpdateLogDataGridView(object sender, EventArgs e) {
// Reload your Log entries from the underlying database.
// You now shall see the LogDataGridView updating itself
// whenever a new log entry is inserted.
}
private Log log;
}