DOBON.NETプログラミング道掲示板
(現在 過去ログ2 を表示中)

[ 最新記事及び返信フォームをトピックトップへ ]

■33400 / inTopicNo.1)  検索結果を任意のタイミングで元フォームに知らせる
  
□投稿者/ み 一般人(19回)-(2016/06/29(Wed) 11:57:03)
  • アイコン環境/言語:[,net4.5 windows10 vs2012 C# SQL-Server2012Express] 
    分類:[.NET] 

    C#フォームの制御に関する質問ですが

    1.フォーム1からフォーム2を呼びます。
    フォーム2はshowで呼出ます

    2.フォーム2は検索画面でデータがリストボックスに
    表示されています。

    3.フォーム2のリストをダブルクリックにより
    フォーム1に検索結果(単票形式の画面)に表示します。

    以上が処理の全てですが問題は
    フォーム2を閉じずにフォーム1のデータ内容を更新したいのです。
    今まではフォーム2をダイアログで開きデータを選択した際、プロパティに
    格納しフォーム2を閉じた時にそのプロパティのキー値を参照して
    データ検索しフォーム1のデータを更新していました。

    それが仕様変更としてフォーム2は表示したまま検索結果をフォーム1に表示するに
    変更したいのですがどのようにフォーム1に検索が実行されたか通知をしらせればいいのでしょうか
引用返信 削除キー/
■33401 / inTopicNo.2)  Re[1]: 検索結果を任意のタイミングで元フォームに知らせる
□投稿者/ み 一般人(21回)-(2016/06/29(Wed) 12:56:24)
  • アイコン
    自己レスです。
    調べた結果下記のようにOwner にて元のメソットを呼べそうです。
    もっとスマート(汎用的な?)処理がありそうですが現在はこれですすめたい思います
    ■フォーム1
            private void button1_Click(object sender, EventArgs e)
            {
                Form2 frm2 = new Form2();
                frm2.Owner = this;
                frm2.ShowDialog();
            }
    
            public void test(string work)
            {
                MessageBox.Show(work);
            }
    
    
    ■フォーム2
            private void Form2_Load(object sender, EventArgs e)
            {
                for (int i = 0; i < 10; i++)
                {
                    listBox1.Items.Add(i);
                }
            }
    
            private void listBox1_DoubleClick(object sender, EventArgs e)
            {
                string work = listBox1.SelectedItems[0].ToString();
                ((Form1)this.Owner).test(work);
            }
    

引用返信 削除キー/
■33402 / inTopicNo.3)  Re[2]: 検索結果を任意のタイミングで元フォームに知らせる
□投稿者/ たーん 一般人(1回)-(2016/06/29(Wed) 20:29:43)
  • アイコン
    子から親を操作するのは行儀が悪いので、
    要件どおり、子から親に通知するようにすると良いです。
    
    具体的にはフォーム2に DataSelected イベントを実装して、フォーム1で受けます。
    リストボックスの SelectedValueChanged イベントをフォームで受けるのと同じです。
    
    ■フォーム1
    
    private void button1_Click(object sender, EventArgs e)
    {
        var frm2 = new Form2();
        frm2.DataSelected += new EventHandler(frm2_DataSelected);
    
        frm2.Show(this);
    }
    
    private void frm2_DataSelected(object sender, EventArgs e)
    {
        MessageBox.Show(“Data Selected!");
    }
    
    
    ■フォーム2
    
    public event EventHandler DataSelected;
    
    private void button1_Click(object sender, EventArgs e)
    {
        DataSelected(this, new EventArgs());
    }
    

引用返信 削除キー/
■33403 / inTopicNo.4)  Re[2]: 検索結果を任意のタイミングで元フォームに知らせる
□投稿者/ 魔界の仮面弁士 大御所(1033回)-(2016/06/30(Thu) 10:07:23)
  • アイコンNo33400に返信(みさんの記事)
    > フォーム2を閉じずにフォーム1のデータ内容を更新したいのです。

    たーんさんから、具体的な実装例が書かれていますように、
    こういう場合にはイベントで通知するのが良いと思います。


    たとえば .NET 標準で、「FontDialog」というコンポーネントがありますよね。
    フォントの選択を行うためのダイアログです。
    http://dobon.net/vb/dotnet/form/fontdialog.html

    これの ShowApply プロパティを使うと [OK] [キャンセル] の他に、
    [適用]ボタンを付けることができるようになっています。

    [適用]ボタンとは、御存知のようにダイアログを閉じることなく、
    設定内容を即時適用させるために使われるボタンなわけですが、
    FontDialog の場合は「Apply イベント」を通じて、フォントが変更された事を
    呼び出し元に伝える仕様になっています。
    http://blog.hiros-dot.net/?p=2231


    No33401に返信(みさんの記事)
    > 調べた結果下記のようにOwner にて元のメソットを呼べそうです。
    > ((Form1)this.Owner).test(work);

    これだと Owner が Form1 でなければなりませんので、汎用性に欠けます。
    たとえば、同じ設定画面を Form10 からも呼び出したい場合に困りますよね。


    必ずオーナーの Test メソッドを呼び出すと言う実装にするのであれば、
    メソッド定義と具体的な実装を分離するようにすると良いでしょう。

    まずは Test メソッドの仕様(戻り値や引数定義)のみを定義した
    インターフェイスを用意します。

    public interface ISampleNotice
    {
      void Test(string data);
    }

    そしてそのインターフェイスを、呼び出し元フォーム(Form1 や Form10)に実装します。

    public partial class Form1 : Form, ISampleNotice
    {
     void INotice.Test(string data)
     {
      MessageBox.Show(data);
     }

     public Form1()
     {
      InitializeComponent();
     }
    }

    その上で、検索ダイアログ側の実装を下記のように変更します。
    これにより、Form1 以外からでも利用可能なダイアログとなりますので、
    元のコードよりも汎用性が高くなりますね。

    private void listBox1_DoubleClick(object sender, EventArgs e)
    {
     string work = listBox1.GetItemText(listBox1.SelectedItem);

     ISampleNotice notice = this.Owner as ISampleNotice;
     if(notice != null)
     {
      notice.Test(work);
     }
    }

引用返信 削除キー/
■33404 / inTopicNo.5)  Re[2]: 検索結果を任意のタイミングで元フォームに知らせる
□投稿者/ 魔界の仮面弁士 大御所(1034回)-(2016/06/30(Thu) 10:23:39)
  • アイコンNo33400に返信(みさんの記事)
    なお、汎用性の件を抜きにしても、
    > Form2 frm2 = new Form2();
    > frm2.Owner = this;
    > frm2.ShowDialog();
    そもそも上記の呼び方は避けた方が良いでしょう。

    MSDN ライブラリの Form.ShowDialog メソッドの解説にも書かれていますように、
    モーダルフォーム(ShowDialog による呼び出し)の場合、Dispose が必須だからです。

    モードレスフォーム(Show メソッドによる呼び出し)の場合は、
    フォームが閉じられると自動的に Dispose されるようになっているのですが、
    モーダルではそうはならないため、呼び出し元がきちんと Dispose を呼ぶべきです。


    たとえば、Form2.designer.cs 内にある

    protected override void Dispose(bool disposing)

    の行にブレークポイントを貼ってから元のコードを実行し、
      検索画面を表示→閉じる→検索画面を再度開く→また閉じる
    という操作を何度か行った後、呼び出し元の Form1 を閉じてみてください。


    Form1 を閉じたとき(というかアプリケーション終了時)には、
    Dispose の行を通過することになりますが、Form2 を閉じただけでは、
    Form2 の Dispose が即時実行されていないことが分かるかと思います。


    ですからこういう場合には

    using (var dlg = new Form2())
    {
     dlg.ShowDialog(this);
    }

    と書くのが良いでしょう。ShowDialog 時には using を併用する事で、
    ダイアログの解放を保証する事ができます。

    ちなみに、オーナーフォームを指定するには、Owner プロパティを使う方法の他、
    上記のように Show や ShowDialog メソッドの引数にて受け渡す手法も使えます。
引用返信 削除キー/



トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

Mode/  Pass/


- Child Tree -