1

UserControlに、コントロールが何をしているのかをホストwindowsformに知らせる機能をどのように含めることができるか教えてもらえますか?

たとえば、私のusercontrolにはファイルブラウザがあり、ユーザーがこのファイルブラウザを使用してファイルを開く場合、フォームのステータスストリップバーに「Loadingfile(s)」と記述します。

これにはイベントの使用が必要ですか?もしそうなら、どうすればusercontrol内に単一のイベントを作成して、それが行うことを報告できますか(その後、usercontrolのすべてのメソッドでこのイベントを呼び出す必要があると思います)。

4

2 に答える 2

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);
    }
}
于 2012-08-29T19:51:23.210 に答える
1

はい、イベントを作成してサブスクライブする必要があります。イベントの標準パターンに従った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;
            ...
        }
    }
}
于 2012-08-29T19:53:42.440 に答える