C# 複数フォームでのやりとり(メインフォームとテキスト入力用フォーム)

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Pa

C# 複数フォームでのやりとり(メインフォームとテキスト入力用フォーム)

#1

投稿記事 by Pa » 4年前

【やりたいこと】
Form1: メインフォーム。ボタンがひとつあり、Form2から取得した内容を表示する。
Form2: テキスト入力用フォーム。テキスト入力欄とOKボタンがある。

やりたいフローは以下のとおりです。

Form1内部にあるボタンをクリック→Form2がモーダルで開く→Form2内にテキストを入力
→Form2内にあるOKボタンクリック→Form2が閉じる→Form1に先ほど入力したテキストが表示される

最後のForm2で入力した値をForm1へと渡す方法が分かりません。
今日はじめてC#プログラムをさわったので、基本的な質問かもしれません。
どうしてもすぐに出来る必要があるのですが、この部分で躓いてしまいました。
C/C++の基本は出来ます。

C#に詳しい方がいれば、是非教えて頂きたいです。
よろしくお願いします!


YuO
記事: 941
登録日時: 9年前
住所: 東京都世田谷区

Re: C# 複数フォームでのやりとり(メインフォームとテキスト入力用フォーム)

#3

投稿記事 by YuO » 4年前

解決となっていますが,方法が書かれていませんし,往々にしてまずい解決方法を採ることがあるので……。

・大きなプログラムで通常推奨される方法
Form2が必要とする情報や設定する情報をクラスにまとめ,そのクラスのインスタンスをForm1とForm2の間でやりとりする。
現実的にはModelに属するクラスを渡すことになるかと思います。
設定系などでキャンセル可能な場合は一度複製したものにデータを設定しておき,ApplyやOKのタイミングで複製したデータを有効化することになります。

コード:

class ProgramSettings
{
    public ProgramSettings ()
    {
        Title = "";
    }

    public ProgramSettings (ProgramSettings other)
    {
        if (other == null) throw new ArgumentNullException(nameof other); // C# 6.0以降。C# 5.0かそれ以前ではnameofが使えないので"other"とする
        this.Title = other.Title;
    }

    public string Title { get; set; } // やりとりする情報。とりあえずはひとつだけ。
}

コード:

public partial class Form2
{
    private ProgramSettings _settings = new ProgramSettings();

    public ProgramSettings Settings
    {
        get { return _settings; }
        set
        {
            if (value == null) throw new ArgumentNullException(nameof Settings);
            _settings = value;
        }
    }

    protected override void OnLoad (EventArgs e)
    {
        base.OnLoad(e);
        TextBox1.Text = _settings.Title;
    }

    private void TextBox1_TextChanged (object sender, EventArgs e)
    {
        _settings.Title = TextBox1.Text;
    }
}

コード:

public partial class Form1
{
    private ProgramSettings _settings; // どこかで代入済み

    private void Button1_Click (object sender, EventArgs e)
    {
        using (var form2 = new Form2())
        {
            var temporarySettings = new ProgramSettings(_settings)
            form2.Settings = temporarySettings ;
            if (form2.ShowDialog(this) != DialogResult.OK) return;

            _settings.Title = temporarySettings.Title; // 目的次第で_settings = temporarySettings;でもよい。
            Label1.Text = _settings.Title;
        }
    }
}
・小さなプログラムで推奨される方法
個々のデータ毎にForm2にプロパティを作成します。
多くの情報を渡そうとすると設定項目が増えるため,あまりに増えた場合は先の方法の方がよいでしょう。

コード:

public partial class Form2
{
    public string TitleSetting
    {
        get { return TextBox1.Text; }
        set
        {
            if (value == null) throw new ArgumentNullException(nameof TitleSetting);
            TextBox1.Text = value;
        }
    }
}

コード:

public partial class Form1
{
    private void Button1_Click (object sender, EventArgs e)
    {
        using (var form2 = new Form2())
        {
            form2.TitleSetting = "" ;
            if (form2.ShowDialog(this) != DialogResult.OK) return;

            Label1.Text = form2.TitleSetting;
        }
    }
}
・ほとんど全ての場合において,推奨されない方法
Form2のTextBox1をinternalやpublicにして,Form1からアクセスを行う

コード:

public partial class Form1
{
    private void Button1_Click (object sender, EventArgs e)
    {
        using (var form2 = new Form2())
        {
            form2.TextBox1.Text = "" ;
            if (form2.ShowDialog(this) != DialogResult.OK) return;

            Label1.Text = form2.TextBox1.Text;
        }
    }
}
この方法を使ってしまうと,例えばForm2の一部をユーザーコントロールとして切り出した場合などに,コードの修正がややこしくなります。
そもそも,他のクラスの内部実装をしらないと使えない時点でクラスとして失格です。

閉鎖

“C言語何でも質問掲示板” へ戻る