好的,我一直在搜索网站和谷歌,并且无法完全了解代表和事件处理程序等方面需要做的事情,所以希望有人可以帮助/解释我需要什么做。
所以,我正在编写一个简单的数据库应用程序(使用SQLite)。有一个主要形式是MDI父级(这基本上是一个大窗口,顶部有菜单)。菜单启动其他窗口,允许查看,编辑和插入数据库的各个表。
其中一个窗口是一个LOG窗口,显示我的日志表。
目前,如果用户在窗口中更改显示TABLE中数据的内容。该操作还会写入日志表。但是,如果“日志”窗口处于打开状态,则日志视图不会更新。
所以,我发现我可能需要从我的LOG窗口“订阅”的TABLE UPDATE代码中“触发”一个事件(因此它可以更新DataGridView)。
我无法弄清楚事件的不同“位”在哪里。
MdiParent是否应该有public delegate void EventHandler();
?如果不在哪里?
哪个班级获得public static event EventHandler logGoneStale;
?
我唯一可以肯定的是,显示日志的窗口(其中有一个名为public void UpdateLogDataGridView()的方法 - 调用数据库对象/方法来(重新)填充datagridview)需要有:
其中有logGoneStale += new EventHandler(UpdateLogDataGridView);
之类的东西。这至少是对的吗?
完全被迷惑 - 似乎MSDN上没有任何事件示例/教程试图做我想要实现的目标。
答案 0 :(得分:0)
您需要在发送事件的类中定义event
,并在应该接收事件的类中附加事件处理程序。为了使事情稍微简单一些,从C#3.5开始,您可以完全忘记delegate
关键字并使用lamba表达式作为事件处理程序。另请注意,在大多数情况下,创建事件static
是没有意义的,因为通常事件是由实例触发的,而不是由类触发的。 / p>
示例:
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();
}
}
我希望这会对你有所帮助。
答案 1 :(得分:0)
使用活动要求您同时拥有活动发布者和活动订阅者。
@chris'回答是正确的。
此外,您需要在最接近您希望收到通知的操作的位置处举起活动。
例如,实现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 Delegate,可能会注意到它的签名等待object
作为第一个参数,即触发事件的对象,以及PropertyChangedEventArgs实例通知有关已更改的财产。
回到您的示例,您希望每当将日志插入基础数据库时都会注意到,以便可以刷新日志窗口。每当您想要使用事件时,都需要回答两个问题。
我的出版商应该是什么?
MdiParent是否应该有
public delegate void EventHandler();
?
简答:不!
如果不在哪里?
事件声明最适合发布商。如果你有一个负责记录的类,那么这就是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;
}