2012-08-29 39 views
1

有人能告诉我如何在我的UserControl中拥有一项功能,这可以让主窗口窗体知道控件在做什么?从UserControl获取更新

例如我的用户控件有一个文件浏览器,如果用户使用这个文件浏览器打开一个文件,我想在我的表单的statusstrip栏中写入“加载文件”。

这是否需要使用事件?如果是这样,我怎么能在usercontrol里面有一个事件来报告它所做的事情(然后我想我必须在usercontrol的所有方法中调用这个事件)。

回答

1

是的,您需要创建一个事件并订阅它。遵循事件的标准模式的一个建议:

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; 
      ... 
     } 
    } 
} 
2

简单

是,暴露用户控件的形式可以订阅的事件。你应该使用标准的事件模式:当文件被打开

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); 
    } 
}