有人能告訴我如何在我的UserControl中擁有一項功能,這可以讓主窗口窗體知道控件在做什麼?從UserControl獲取更新
例如我的用戶控件有一個文件瀏覽器,如果用戶使用這個文件瀏覽器打開一個文件,我想在我的表單的statusstrip欄中寫入「加載文件」。
這是否需要使用事件?如果是這樣,我怎麼能在usercontrol裏面有一個事件來報告它所做的事情(然後我想我必須在usercontrol的所有方法中調用這個事件)。
有人能告訴我如何在我的UserControl中擁有一項功能,這可以讓主窗口窗體知道控件在做什麼?從UserControl獲取更新
例如我的用戶控件有一個文件瀏覽器,如果用戶使用這個文件瀏覽器打開一個文件,我想在我的表單的statusstrip欄中寫入「加載文件」。
這是否需要使用事件?如果是這樣,我怎麼能在usercontrol裏面有一個事件來報告它所做的事情(然後我想我必須在usercontrol的所有方法中調用這個事件)。
是的,您需要創建一個事件並訂閱它。遵循事件的標準模式的一個建議:
enum ControlStatus {Idle, LoadingFile, ...}
class StatusChangedEventArgs : EventArgs
{
public ControlStatus Status {get; private set;}
public StatusChangedEventArgs(ControlStatus status)
: base()
{
this.Status = status;
}
}
partial class MyControl : UserControl
{
public ControlStatus Status {get; private set;}
public event EventHandler<StatusChangedEventArgs> StatusChanged;
protected virtual void OnStatusChanged(StatusChangedEventArgs e)
{
var hand = StatusChanged;
if(hand != null) hand(this, e);
}
void LoadFiles()
{
...
Status = ControlStatus.LoadingFiles;
OnStatusChanged(new StatusChangedEventArgs(this.Status));
...
Status = ControlStatus.Idle;
OnStatusChanged(new StatusChangedEventArgs(this.Status));
}
}
partial class MyHostWindowsForm : Form
{
public MyHostWindowsForm()
{
var ctl = new MyControl();
...
ctl.StatusChanged += ctl_StatusChanged;
}
void ctl_StatusChanged(object sender, StatusChangedEventArgs e)
{
switch(e.Status)
{
case ControlStatus.Idle:
statusStripBar.Text = null;
break;
case ControlStatus.LoadingFiles:
statusStripBar.Text = "Loading file(s)";
break;
...
}
}
}
簡單
是,暴露用戶控件的形式可以訂閱的事件。你應該使用標準的事件模式:當文件被打開
class MyUserControl : UserControl
{
public event EventHandler<EventArgs> FileOpened;
protected virtual void OnFileOpened(EventArgs e)
{
EventHandler<EventArgs> handler = FileOpened;
if (handler != null)
handler(this, e);
}
}
然後調用OnFileOpened(EventArgs.Empty)
其觸發事件。
使用自定義的EventArgs
現在的形式很可能需要知道被打開了哪些文件。你可以在公開的表格可以用來找出用戶控件的屬性,也可以提供這些信息在你的事件,像這樣:
public class FileOpenedEventArgs : EventArgs
{
private string filename;
public FileOpenedEventArgs(string filename)
{
this.filename = filename;
}
public string Filename { get { return filename; } }
}
class MyUserControl : UserControl
{
public event EventHandler<FileOpenedEventArgs> FileOpened;
protected virtual void OnFileOpened(FileOpenedEventArgs e)
{
EventHandler<FileOpenedEventArgs> handler = FileOpened;
if (handler != null)
handler(this, e);
}
}
然後你OnFileOpened(new FileOpenedEventArgs(filename))
觸發事件。
最優
當你創建一個事件處理程序public event delegate Name;
,你分配你的對象的委託保管。對象(尤其是控件)通常具有大量從不訂閱的事件。這是一大堆沒有被使用的分配存儲。在框架中有一個以EventHandlerList爲形式的優化。這個方便的對象只有在實際使用時才存儲事件處理程序。所有System.Windows.Forms.Control
對象都來自System.ComponentModel.Component
,它已經提供了一個(受保護的)EventHandlerList,您可以在派生控件中訪問該對象。
要使用它,首先要創建一個可以唯一標識事件的靜態對象,然後手動提供add {}
和remove {}
方法。像這樣:
class MyUserControl : UserControl
{
private static readonly object FileOpenedKey = new Object();
public event EventHandler<FileOpenedEventArgs> FileOpened
{
add { Events.AddHandler(FileOpenedKey, value); }
remove { Events.RemoveHandler(FileOpenedKey, value); }
}
protected virtual void OnFileOpened(FileOpenedEventArgs e)
{
var handler = (EventHandler<FileOpenedEventArgs>)Events[FileOpenedKey];
if (handler != null)
handler(this, e);
}
}