2

私は2つのフォームを持っています。すべてのメイン コードが実行されている場所。このメソッドを使用してメニュー項目をクリックすると、別のフォームが表示されます。

Form2 videoSettings = new Form2();       

private void videoToolStripMenuItem_Click(object sender, EventArgs e)
{
    videoSettings.Show();
}

次に開かれるフォームには、ユーザーがアプリケーションの設定を行うためのフィールドが含まれています。 ここに画像の説明を入力 次に、「保存」ボタンをクリックすると、この変数public int deviceIndex; が必要になります。元のフォームから取得されます。

ですから、videoSettings (Form2) で保存ボタンがクリックされたことを検出するイベントまたは何かを Form1 に追加できるかどうか疑問に思っています。

4

5 に答える 5

6

私はそれを別の方法で行います。UI 処理レイヤーとビジネス ロジック レイヤーの間でコードを分離します。したがって、シナリオは次のように実行されます。

  1. 最初のフォームは、特定のセマンティクスを持つボタンがアクティブになったことを通知するイベントを発行します。処理に必要なデータは、イベントのデータに含まれています。
  2. ビジネス ロジックはこのイベントをリッスンし、2 番目のフォームでコマンドを発行することを決定します。フォームのクラスで適切なメソッドを呼び出し、必要な情報をパラメーターとして渡します (必要に応じてパラメーターを前処理することもあります)。
  3. 2 番目のフォームは、ビジネス ロジックからコマンドを受け取り、ビューを更新します。

この方法では、問題はまったく発生しません。


例: (私は winforms の専門家ではありません。winforms のベスト プラクティスの POV からは完全に間違っている可能性があることに注意してください。)

パート 1 (最初のフォーム):

class ProcessingActivatedEventArgs : EventArgs
{
    public ProcessingActivatedEventArgs(int data) { MoreData = data; }
    public int MoreData { get; protected set; }
}

class Form1 : Form
{
    private int currentData;
    public event EventHandler<ProcessingActivatedEventArgs> ProcessingActivated;
    void OnButtonClick(object sender, EventArgs args)
    {
        // ...
        if (ProcessingActivated != null)
            ProcessingActivated(new ProcessingActivatedEventArgs(currentData));
    }
}

パート 2: (ビジネス ロジック)

class Controller
{
    Form1 f1;
    Form2 f2;

    void StartFirstForm()
    {
        f1 = new Form1();
        f1.ProcessingActivated += OnProcessingActivated;
        f1.Show();
    }

    void OnProcessingActivated(object sender, ProcessingActivatedEventArgs args)
    {
        int data = args.MoreData;
        f1.DisableProcessingRequests();
        model.ProcessingFinished += OnProcessingFinished;
        model.StartProcessing(data);
        if (data > 0)
            f2.DisplayDataProcessing(0, data);
        else if (data < 0)
            f2.DisplayDataProcessing(data, 0);
        else
            throw new SomeCoolException("impossible data");
    }
}

パート 3: (第 2 形態)

class Form2 : Form
{
    public void DisplayDataProcessing(int lower, int upper)
    {
        // ... update the UI
    }
}

この実装は、Controllerと フォームを実際よりも緊密に結び付けていることに注意してください。WPFでは、適切なものを使用してデカップリングを実現していますDataContext(ただし、WinFormsで適切に行う方法はわかりません)。

于 2012-07-01T17:07:25.947 に答える
1

多くの提案がありますが、2 セント追加したいと思います。

form2.ShowDialog(); を使用できます。これにより、form2 が閉じられるまで form1 スレッドの実行が停止されます。つまり、form1 からこれを行うことができます。

Form2 videoSettings = new Form2();  

//show options
videoSettings.ShowDialog();

//at this point, the user has either clicked save, cancel, or closed the form 
//(because the form is closed, obviously :) )
int device = videoSettings.deviceIndex;

そのようにフォームをロックできない場合は、Form2 でイベントを使用する別の方法を次に示します。

Form2 : Form
{
    public event EventHandler Saved;

    OnSaveButtonClicked(...)
    {
        if(Saved != null) Saved(this, new EventArgs());
    }
}

次に Form1 から:

Form2 frm = new Form2();
frm.Saved += (s, e) =>
{
    //saved button clicked, retrieve value.
    //also could be handled as a method, or really any way.
};
frm.Show();
于 2012-07-01T17:21:50.677 に答える
1

最も単純な ShowDialog() と、ビジネス ロジックとインターフェイスを分離する精巧な方法との間の別の方法を提案させてください。

Form2 で新しいイベントを作成したいと考えています。私はこれをイベントと呼んでいますSettingsSaved

Form2 でグローバル宣言として追加

public delegate void SettingsSavedEventHandler(object sender, SettingsSavedEventArgs e);
public event SettingsSavedEventHandler SettingsSaved;

および cmdSave_Click イベントで

if(SettingsSaved != null)
{
    SettingsSavedEventArgs ss = new SettingsSavedEventArgs() { DeviceIndex = deviceIndex};
    SettingsSaved(this, ss); 
}

クラス SettingsSavedEventArgs のスケルトン

public class SettingsSavedEventArgs: EventArgs
{
    public int DeviceIndex {get; set;}  
    // Other settings could be added here
}

Form2 を呼び出すコードで、イベントをサブスクライブし、ユーザーが Form2 の [保存] ボタンをクリックしたときに通知を受け取ることができます。

Form2 videoSettings = new Form2();
videoSettings.SettingsSaved += new SettingsSavedEventHandler(SavedHandler);
videoSettings.Show();     
....

private void SavedHandler(object sender, SettingsSavedEventArgs ss)
{
    int deviceIndex = ss.DeviceIndex;
}

オブザーバー パターン

于 2012-07-01T17:41:24.083 に答える
0

このような情報を渡すことができます

private Form1 mainForm = null;
public Form2(Form callingForm)
{
    mainForm = callingForm as Form1; 
    InitializeComponent();
}

次に、次のようにForm2からForm1プロパティにアクセスできます。

//Call this in Save button click event 
this.mainForm.deviceIndex;
于 2012-07-01T17:16:02.443 に答える
0

おそらく、INotifyPropertyChangedインターフェイスを実装する 2 番目のフォームを作成することができます。次に、[保存] をクリックすると、PropertyChangedイベントが発生し、最初のフォームでキャプチャされます。

于 2012-07-01T17:10:23.123 に答える