0

私は常にフォームの修飾子をプライベートに設定していますが、内部もパブリックも好きではありません。

今まで、私はこのように呼び出していました:

public string Addtext
{
    if(InvokeRequired)
    {
         Invoke((MethodInvoker)delegate
         {
             textbox.text = value;
         });
    }
    else
        textbox.text = value;
}

しかし、フォームのすべてのメンバーにそのようなプロパティを追加することは、オブジェクト指向ではありません。

パラメータ(アクション)を呼び出す関数を作成したいです。最善を尽くしましたが、失敗しました-フォームメンバーがパブリックまたは内部である必要があります:(

    public void PerformActionOnForm(Action<FormMain> action)
    {
        var form = Form.ActiveForm as FormMain;
        object s = action.Clone();
        if (form != null)
        {
            form.PerformAction(action);
        }
    }

    public void PerformAction(Action<FormMain> action)
    {
        if (InvokeRequired)
            Invoke(action, this);
        else
            action(this);
    }

私のコードの2つの問題:

変更したいプロパティを != private にする必要があります:(

フォームがフォーカスされていない場合は機能しません。

4

3 に答える 3

2

「まったくオブジェクト指向ではない」フォームの範囲外でアクセスまたは設定する必要があるデータのプロパティをどのように追加していますか? これは本当に唯一のオプションです。匿名デリゲート (または任意のデリゲート) のコードは、宣言されたコンテキストで実行されます。可視性の問題を回避するための唯一の機能はリフレクションであり、それは大きなコードの臭いです。プロパティを作成し、必要に応じて使用します。

2番目のオプションについては、「メインフォーム」でこれを実行したいと考えています。ここには 2 つのオプションがあります。インスタンスが 1 つしかないと仮定し、それをクラスの静的プロパティとして保持し、インスタンス コンストラクターで割り当てます。

public partial class MainForm : Form
{
    private static MainForm singletonInstance;

    public static MainForm SingletonInstance
    {
        get { return singletonInstance; }
    }

    public MainForm() : base()
    {
        InitializeComponent();

        singletonInstance = this;
    }
}

public void PerformActionOnForm(Action<FormMain> action)
{
    var form = MainForm.SingletonInstance;
    // object s = action.Clone(); What was this for?
    if (form != null)
    {
        form.PerformAction(action);
    }
}

もう 1 つは、すべてのフォームが適切に「所有」されており、所有者のいない唯一のフォームがメイン フォームである場合にのみ機能します。その場合、これを行うことができます:

public void PerformActionOnForm(Action<FormMain> action)
{
    var form = Form.ActiveForm.TopLevelControl as FormMain;
    // object s = action.Clone(); What was this for?
    if (form != null)
    {
        form.PerformAction(action);
    }
}
于 2009-04-28T15:14:47.723 に答える
1

非 UI スレッドからの UI コンポーネントの呼び出し

メッセージ ループが 1 つだけあると仮定すると (99% はそうです)、次のようになります。

public static class SynchronizedInvoker
{
    public static void Invoke(Action action)
    {
        Form form = Application.OpenForms.Cast<Form>().FirstOrDefault();
        if (form != null && form.InvokeRequired)
            form.Invoke(action);
        else
            action();
    }
}

コードの呼び出し:

SynchronizedInvoker.Invoke(() => myForm.Text = myText);

プライベート UI コンポーネントへのアクセス

プライベート UI メンバーへのアクセスは、.NET オブジェクトへの他のプライベート メンバーへのアクセスと同じです。他のオブジェクトからアクセスできないのは、プライベート メンバーの性質です。それでもアクセスが必要な場合は、UI コンポーネントの参照を呼び出し元に渡すか、リフレクションを使用してプライベート オブジェクトへのパスを解決する必要があります。

UI コンポーネントの参照を呼び出し元に渡す例:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        ThreadPool.QueueUserWorkItem(delegate { MyWorker.Run(button1); }); 
    }
}

class MyWorker
{
    public static void Run(Button button)
    {
        SynchronizedInvoker.Invoke(() => button.Text = "running");
        Thread.Sleep(5000); // do some important work here
        SynchronizedInvoker.Invoke(() => button.Text = "finished");
    }
}

リフレクションの使用は技術的には可能ですが、理想的ではありません。プライベート メンバーへのパスを知る必要があり、それにはオブジェクトの内部に関する情報が必要です。そもそもなぜ非公開にしたのかを自問する必要があります。

于 2009-04-28T16:49:55.810 に答える
0

他のスレッドから呼び出される可能性のあるフォームへのエントリ ポイントが非常に多くあるのはなぜですか? スレッド マーシャリングを下の方で行うと (フォームのコントローラーが役立つ場合があります)、このようなボイラープレート コードについて心配する必要はありません。

于 2009-04-28T15:48:42.527 に答える