有人能告诉我如何在我的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);
}
}