プロが教えるわが家の防犯対策術!

こんにちは。ユーザーコントロール内のボタンをクリックした時、そのユーザーコントロールをおいている親フォーム側で、それを知るにはどのようにすればよいでしょうか?

----------------------------------------------------------------------
[Form1.cs]

void Inform_UserControlButton1Click()
{
//親が持っている変数を使って処理を行いたい
}

void Form1_Load(....)
{
//ユーザコントロールを設置
UserControl1 ctrl = new UserControl1();
this.Controls.Add(ctrl);

  //ユーザコントロール内のbutton1を見つける
List<Control> ctrl = new List<Control>(cps.Controls.Find("button1", false));

//Form1が持っている変数を使う為の関数を通るようにしたい
(Button)ctrl[0].Click += new System.EventHandler(Inform_UserControlButton1Click); //←エラー
}
----------------------------------------------------------------------
[UserControl.cs]
button1が配置されています。

----------------------------------------------------------------------
こんな感じにしてできないかなー?と思っていたのですが、//←エラーのところで、

イベント 'System.Windows.Forms.Control.Click' は += または -= の左側にのみ表示されます。

となってしまい上手くいきません。
どのようにすればよいでしょうか?

このQ&Aに関連する最新のQ&A

A 回答 (3件)

> ((Button)ctrl[0]).Click += new EventHandler(Inform_UserControlButton1Click);


> では、+=の左側にだけ~・・・というエラーが出ます。

えっと、動いたものを貼り付けたので、コンパイルエラーにはならないはずです。

で、上記コードは、質問時の記述だと左辺が
(Button)ctrl[0].Click
となっていると思います。これだと確かにエラーになります。
しかし
((Button)ctrl[0]).Click
と、キャストを括弧で括って優先させるとエラーにならないと思いますが、
いかがでしょうか?
    • good
    • 2
この回答へのお礼

うは;申し訳ございません。おっしゃるとおりでした。
()のつけ方を見間違っていました。大変失礼致しました。

なるほどです。理解できました。
上記修正を行い、思ったとおりの動作にすることができました。

すばやい対応をしていただき、大変助かりました。ありがとうございました!

お礼日時:2013/01/21 16:43

コメント全然読んでませんでした。


多分、こういうことですかね。

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

  private void Form1_Load(object sender, EventArgs e)
  {
    //ユーザコントロールを設置
    UserControl1 cps = new UserControl1();
    this.Controls.Add(cps);

    //ユーザコントロール内のbutton1を見つける
    List<Control> ctrl = new List<Control>(cps.Controls.Find(@"button1", false));

    //Form1が持っている変数を使う為の関数を通るようにしたい
    ((Button)ctrl[0]).Click += new EventHandler(Inform_UserControlButton1Click);
  }

  private void Inform_UserControlButton1Click(object sender, EventArgs args)
  {
    Console.WriteLine("hoge");
  }
}

この回答への補足

お世話になっております。
入れ違いで投稿してしまったようです。(No1のご回答のほうへ返信していました。)

内容的には、おっしゃるとおりです。そのような事をしたいのですが、No2でnaktakさんが書いてくださったような

((Button)ctrl[0]).Click += new EventHandler(Inform_UserControlButton1Click);

では、+=の左側にだけ~・・・というエラーが出ます。

No1で教えて頂き、また、No1の返信で私が書いたように
((UserControl1)ctrl[0]).button1.Click += new EventHandler(Inform_UserControlButton1Click); //-----(1)
とすればコンパイルは通りますが、実行時エラーでキャストできません、となってしまいました。

補足日時:2013/01/21 16:04
    • good
    • 0

こういうことですか?



cps.Controls.Find("button1", false)
cpsがどこからきたのか分かりません。

ctrl変数が重複しているのでよく分かりません。]

勘というか、やれる方法で書いてます。

UserControlを操作するんですから、UserControl内のButtonのModifiersプロパティはPublicか
Internal、もしくはProtected Internalでないとダメです。


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

  private void Form1_Load(object sender, EventArgs e)
  {
    //ユーザコントロールを設置
    UserControl1 button = new UserControl1();
    button.Name = @"button1";
    this.Controls.Add(button);

    //ユーザコントロール内のbutton1を見つける
    List<Control> ctrl = new List<Control>(this.Controls.Find(@"button1", false));

    //Form1が持っている変数を使う為の関数を通るようにしたい
    ((UserControl1)ctrl[0]).userControlInnnerButton1.Click += new EventHandler(Inform_UserControlButton1Click);
  }

  private void Inform_UserControlButton1Click(object sender, EventArgs args)
  {
    Console.WriteLine("hoge");
  }
}
    • good
    • 0
この回答へのお礼

早速のご回答、ありがとうございます。
参考コードの誤記について、申し訳ございません。

naktakさんの書いて下さった方を元にして修正しました。
また、ユーザコントロール内のボタンのModifireはprivateのままでしたので、publicに変更致しました。
--------------------------------------------------------------------
public partial class Form1 : Form
{
  public Form1()
  {
    InitializeComponent();
  }

  private void Form1_Load(object sender, EventArgs e)
  {
    //ユーザコントロールを設置
    UserControl1 usrCntrl = new UserControl1();//ボタンはこのユーザコントロールにデザイナ上で元から設置してあります。
    this.Controls.Add(usrCntrl);

    //ユーザコントロール内のbutton1を見つける
    List<Control> ctrl = new List<Control>(usrCntrl.Controls.Find(@"button1", false));

    //Form1が持っている変数を使う為の関数を通るようにしたい
    ((UserControl1)ctrl[0]).button1.Click += new EventHandler(Inform_UserControlButton1Click); //-----(1)
  }

  private void Inform_UserControlButton1Click(object sender, EventArgs args)
  {
    Console.WriteLine("hoge");
  }
}
--------------------------------------------------------------------

-----(1) の所のキャストの仕方を上記にするとコンパイルは通るようになったのですが、実行時エラーで、----(1)の箇所で

型 'System.Windows.Forms.Button' のオブジェクトを型 'Application1.UserControl1' にキャストできません。

とエラーになってしまいました。

(Button)((UserControl1)ctrl[0]).button1.Click
(Button)(((UserControl1)ctrl[0]).button1).Click
のような書き方では、初めの、+=の左側にしか置けません、のコンパイルエラーになるようです。

そもそも無理な事をしようとしているのでしょうか・・・?

お礼日時:2013/01/21 15:54

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qユーザコントロールのイベント取得について(C#)

環境:Visual Studio 2005 C# Windows Application
フォームに自作のユーザコントロールを貼り付けてそのイベントを取得する勉強をしているものです。

フォームでのユーザコントロールイベントを取得して処理をする方法が分かりません。

状況
ユーザコントロールにはテキストボックスを追加しています。
また、フォームにそのユーザコントロールを追加しています。

確認したいことは、ユーザコントロールのテキストボックスになにか値を入力したタイミングでチェンジイベントをフォーム側で察知し、処理をするというものです。

どなたか、要点だけでもいいので教えていただけないでしょうか?

宜しくお願いいたします。

Aベストアンサー

外部用のdelegateとコントロールで発生するイベント、内部コントロールで発生するイベントの関連付けを行いましょう

コントロール側のソースのclass定義の外で

  public delegate void ChangeEventHandler(object sender, EventArgs e);
といったデリゲートを設置します

コントロールのクラス定義の中で
// 外部で使うイベント名を定義 ... Changedを使用
public event ChangeEventHander Changed;
// 内部で発生したイベントを外部に知らせる
protected void OnChange( EventArgs e )
{
  // 外部のイベントハンドラが接続されているなら
  if ( Changed != null ) {
    Changed( this, e )
  }
}

private textBox1_TextChanged(object sender, EventArgs e)
{
  // 内部のイベントハンドラを呼び出す
  OnChaned(e);
}

といった記述になります

利用する側では
デザイナでコントロールを選択してプロパティウィンドウをイベントタブに切り替えて『Changed』ハンドラを追加するか

コードで
private void OnChanged(object s, EventArgs e)
{
  MessgeBox.Show("sampel");
}

private void Form_Load(object sender, EventArgs e)
{
  // コントロールのChangedイベントハンドラの設定
  UserControl1.Changed += new ChangeEventHandler( OnChanged )
}
といった具合にします

外部用のdelegateとコントロールで発生するイベント、内部コントロールで発生するイベントの関連付けを行いましょう

コントロール側のソースのclass定義の外で

  public delegate void ChangeEventHandler(object sender, EventArgs e);
といったデリゲートを設置します

コントロールのクラス定義の中で
// 外部で使うイベント名を定義 ... Changedを使用
public event ChangeEventHander Changed;
// 内部で発生したイベントを外部に知らせる
protected void OnChange( EventArgs e )
{
  /...続きを読む

QC#で親にイベントを投げる方法

すごく基本的なことかもしれないのですが、ポインタだけでも良いので教えてください。

あるFormにPictureBoxをはりつけてあります。
PictureBoxをマウスでクリックしたときにpictureBox_Click()イベントが発生しますが、このイベントをそのままスルーして、Formに伝えてあげたいのです。
pictureBox.Parent.OnMouseDown()とでもすればいいのかと思っていたのですが、コンパイルエラーでした。
何かすごい勘違いをしているような気もするのですが、お恥ずかしいことに何が悪いのかよくわかりません。ポインタだけでも良いので、どうすれば親にイベントを投げられるのかを教えてください。

Aベストアンサー

>Formに伝えてあげたいのです
この言葉がなにを意味しているのかはよくわかりませんが。

もし、Formオブジェクト上で定義したメソッドを
呼ぶようにしたいという話なら簡単です。

Formのクラスの中に、
PictureBox1という名前のPictureBox型のメンバー変数があったとします。
Formのクラスの中に、
PictureBox1_Click()というメソッドがあったとします。
初期処理のどこかで、
PictureBox1.OnClick +=
new ○○EventHandler(PictureBox1_Click);
の記述があれば、
PictureBox1からClickイベントが発生した時、
つまり、画面上でクリックされたときに、
Formクラスにある
PictureBox1_Click()メソッドが呼ばれます。
PictureBox1_Click()メソッドはFormクラスの
メソッドなので、その定義の中でのthisは
フォームオブジェクトそのものです。
そうやってフォームオブジェクトにアクセスできます。

なお、この

PictureBox1.OnClick +=
new ○○EventHandler(PictureBox1_Click);

のコードはVisual Studioのデザイナで
PictureBox1のイベントハンドラを登録すると、
InitialComponent()などというメソッドに
(名前ははっきり覚えてません)勝手に追加されます。
本当は別にどこでもよいです。
初期化処理のところで自分で手で追加しても同じことです。


ご質問ないようは、これでよろしかったでしょうか?

ちなみに、
pictureBox.Parent.OnMouseDown()
ですが、
pictureBox.Parentは
コントロールや、コンテナ型のようなものが
返却されるかと、そのオブジェクトは
OnMouseDownというメソッドは保有していないでしょう。
pictureBox.Parentが貴方が定義した
Formクラスの派生クラスということは、
PictureBoxにはわからないことです。


ご質問内容がいまいちよくわからないので、
想像で勝手に回答しましたが、
勘違いしているようであれば、すいません。

以上です。

>Formに伝えてあげたいのです
この言葉がなにを意味しているのかはよくわかりませんが。

もし、Formオブジェクト上で定義したメソッドを
呼ぶようにしたいという話なら簡単です。

Formのクラスの中に、
PictureBox1という名前のPictureBox型のメンバー変数があったとします。
Formのクラスの中に、
PictureBox1_Click()というメソッドがあったとします。
初期処理のどこかで、
PictureBox1.OnClick +=
new ○○EventHandler(PictureBox1_Click);
の記述があれば、
PictureBox1からClickイベントが...続きを読む

Qユーザーコントロールを動的に切り替えたい

visual C# 2010 Express を使用しています。

例えばWPFで新しいプロジェクトを立ち上げるとMainWindow.xamlがあって
そのウインドウの中にはGridが内装されていると思います。
そこで、UserControl1.xamlとUserControl2.xamlを追加して
最初はMainWindowのGridにはUserControl1を貼っておきます。
そしてMainWindowのボタンかなにかをクリックしたら
プログラムで動的にUserControl2に貼り替えたいのですが、
MainWindowクラス内でthis.(ここでプロパティやメンバを)候補を探しても
gridなどが見つからないのです・・・
どうやったら(なにで)動的にこのような切り替えをすることができるのでしょうか?

Aベストアンサー

VSのみだとVSMは使いにくい点も多いです。
なので,VSのみであるならば,コンバーター使って処理する方がお薦めになります。


> すいません、それとGridにはUserControl1が乗っているはずなのですが、
> プロパティやイベントを見てもUserControl1というのがないのですが(あればそこを切り替えれる)
> GridのどこにUserControl1はあるのでしょうか?

UserControlに名前をつけて下さい。
その名前で,Windowのフィールドとしてオブジェクトが存在します。


> クリックしたときに、ただユーザーコントロールの表示の切り替えをするのではなくて
> データベースを使った認証処理などプログラム的な処理も行いたいので、
> やはりなにかとコードから扱えた方が良いかと思うのですが、
> そこらへんもふくめて教えていただけないでしょうか?

このくらいだと,認証用ダイアログでMessangerやそれに似た機構を用意する必要があるくらいで,
あとはコードでUIを触る必要はなさそうです。

WinForms時代から,.NET FrameworkにはData Bindingという仕組みがあります。
さらに,WPFではCommand BindingやConverterといった仕組みが加わりました。
これらの仕組みによって,コードからUIを触る必要はそれほどなくなります。

例えば,
namespace WpfApplication1
{
public class Foo : System.ComponentModel.INotifyPropertyChanged
{
private bool _authorized = false;
private UserControl1ViewModel _uc1Model;
private UserControl2ViewModel _uc2Model;

public Foo ()
{
_uc1Model = new UserControl1ViewModel(this);
_uc2Model = new UserControl2ViewModel(this);
}

public bool Authorized
{
get { return _authorized; }
set
{
_authorized = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("Authorized"));
PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("NotAuthorized"));
}
}
}
public bool NotAuthorized { get { return !Authorized; } }
public UserControl1ViewModel ModelForUserControl1 { get { return _uc1Model; } }
public UserControl2ViewModel ModelForUserControl2 { get { return _uc2Model; } }
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
}
}
なんてクラスがViewModelとしてあったとして,
<Window xmlns:local="clr-namespace:WpfApplication1">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter1" />
</Window.Resources>
<Window.DataContext>
<local:Foo/>
</Window.DataContext>
<Grid>
<local:UserControl1 Visibility="{Binding Path=NotAuthorized, Converter={StaticResource BooleanToVisibilityConverter1}}" DataContext="{Binding ModelForUserControl1}" />
<local:UserControl2 Visibility="{Binding Path=Authorized, Converter={StaticResource BooleanToVisibilityConverter1}}" DataContext="{Binding ModelForUserControl2}" />
</Grid>
</Window>
のような記述をすれば,Foo.Authorizedの値の設定によってUserControl1とUserControl2の表示を切り替えられます。
# XAMLはだいぶ手抜きをしています。

VSのみだとVSMは使いにくい点も多いです。
なので,VSのみであるならば,コンバーター使って処理する方がお薦めになります。


> すいません、それとGridにはUserControl1が乗っているはずなのですが、
> プロパティやイベントを見てもUserControl1というのがないのですが(あればそこを切り替えれる)
> GridのどこにUserControl1はあるのでしょうか?

UserControlに名前をつけて下さい。
その名前で,Windowのフィールドとしてオブジェクトが存在します。


> クリックしたときに、ただユーザーコントロールの...続きを読む

Q【C#】 あるイベントから別イベントを呼び出す。

タイトルの通り、あるイベント内から別イベントの処理を呼び出したいと
考えています。ですが、方法がわかりません。

【質問投稿に至った経緯】
現状は、検索から一覧を表示し1つを選択、選択した内容の更新を行なうプログラムを作成しています。選択した内容を更新するところまではできました。ただ、更新内容を確認できるよう一覧画面に前回検索した内容を一覧表示させたいと考えています。この時、検索イベントを呼び出し、一覧を再表示させようと思っています。

Aベストアンサー

「検索イベント」とは、[検索]ボタンをクリックした時の
イベント処理の事でしょうか?
それならば、一覧表示処理を別ルーチンに分けて、[検索]
ボタンClickイベントと同じルーチンをCallする様にすれば
良いと思いますが?

QC# ログイン画面からメイン画面への画面遷移について

C# ログイン画面からメイン画面への画面遷移について

C#での画面遷移に関する質問です。
ログイン画面からメイン画面に遷移する場合、どの様な方法で遷移すれば良いのか
迷っています。

現状では以下の方法で遷移していますが、より適切な方法をご存じの場合
ご教示下さい。

(1)Program.csにおいてApplication.Run(new LoginDialog())で
ログイン画面を表示

(2)ログインボタンクリックメソッドでログイン成功時、
メイン画面インスタンスを生成・表示し、ログイン画面を非表示。
(後でログイン画面を再表示することがある為)

---------------------------------------------------------------------
private void LoginButton_Click(object sender, EventArgs e)
{
   /* ログイン処理 */

   //ログイン成功時
   //メイン画面インスタンス生成
   MainForm mainForm = new MainForm();
   //ログイン画面インスタンスを代入
   mainForm.loginForm = this;
   //メイン画面表示
   mainForm.Show();
   //ログイン画面非表示
   this.Visible = false;
}
---------------------------------------------------------------------

また上記の方法だとメイン画面を閉じても、アプリケーションは終了しない為
メイン画面の閉じるボタンを押した場合に以下の処理を行っています。

---------------------------------------------------------------------
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
   //ログイン画面クローズ
   loginForm.Close();
}
---------------------------------------------------------------------

以上、宜しくお願いします。

C# ログイン画面からメイン画面への画面遷移について

C#での画面遷移に関する質問です。
ログイン画面からメイン画面に遷移する場合、どの様な方法で遷移すれば良いのか
迷っています。

現状では以下の方法で遷移していますが、より適切な方法をご存じの場合
ご教示下さい。

(1)Program.csにおいてApplication.Run(new LoginDialog())で
ログイン画面を表示

(2)ログインボタンクリックメソッドでログイン成功時、
メイン画面インスタンスを生成・表示し、ログイン画面を非表示。
(後でログイン画面を再表示す...続きを読む

Aベストアンサー

#2です。
最初にログイン画面のみを表示したいなら
メイン画面のForm_menu_Load(loadイベント処理)
の中で、ログイン画面をモーダル表示し、
NGならメイン画面のcloseのほうがよいかも知れません。

QC#にて別クラスの関数を使いたい

C#にて、別クラスの関数を使用する方法を教えてほしいです。

下記のような、構造体を受け取るメソッドを作りました。

*****************************
private struct MyPoint
{
public int x;
public int y;
}

private void proc1(MyPoint pt)
{
MessageBox.Show("座標:" ; pt.x + "," + pt.y + "実行結果");
}

private void button1_Click(object sender ,System.EventArgs e)
{

MyPoint pt;
pt.x = 10;
pt.y = 20;
proc(pt);
}
*****************************

別のフォームのクラスから、proc1を呼び出したいのですが、やり方がわかりません。
どうか、教えてください。

Aベストアンサー

同じ定義をしたとしても別の名前空間に書いた構造体は同一とはみなされません。

呼び出し先クラスでの構造体を private では無く、public で宣言して下さい。

呼び出し元では、

MyClass.MyPoint pt;

のようにして実体を作ります。

QC#「オブジェクト参照が必要です」(初心者)

Visual C# 2008を学習中なんですが、とりあえず何か作ってみようと思って、パラパラマンガに挑戦してみました。
Form1にpictureBox1を作り、waitを入れてイメージを書き換えるという単純なものです。
ところが実行しようと思ったら、「静的でないフィールド、メソッド、またはプロパティ’WindowsFormApplication1.Form1.pictureBox1’でオブジェクト参照が必要です」というエラーが出ます。その際のフォーカスは、main()内の
Form1.pictureBox1.image = Image.FromFile("motion1.png");
”Form1.pictureBox1”に当てられています。

何が原因と考えられるでしょうか。
もし情報不足であればご指摘いただくか、あるいはこの目的においてやらなければいけないこと、を大雑把に教えていただくだけでも幸いです。
よろしくお願いします。

Aベストアンサー

main()内に記述されているとのことですので、たぶん、
Form1.pictureBox1.Image=Image.FromFile("motion1.png");
Application.Run(new Form1());
と書いているのではないでしょうか?

連載 改訂版 C#入門 第3章 クラスとインスタンス
http://www.atmarkit.co.jp/fdotnet/csharp_abc2/csabc2_003/cs2_003_01.html#cs0302

ここであるように、オブジェクト指向にはクラスとインスタンスという概念があります。
今のコードでは、Form1クラスを操作しようとしているのでそのようなエラーが出ます。

具体的な解決方法としては、PictureBoxに初期画像を設定する処理をForm1のコンストラクタでやるのがいいと思います。
その際、redfox63さんがおっしゃられるように
this.pictureBox1
と記述することが必要です。(thisは自分自身のインスタンスを指します)

後は、Windowsフォームで一定間隔での処理をするための「Timerコンポーネント」について調べてみたらいいと思います。

タイマにより一定時間間隔で処理を行うには?(Windowsタイマ編)
http://www.atmarkit.co.jp/fdotnet/dotnettips/372formstimer/formstimer.html

MSDNライブラリ Timerクラス
http://msdn.microsoft.com/ja-jp/library/system.windows.forms.timer.aspx

参考URL:http://www.atmarkit.co.jp/fdotnet/csharp_abc2/index/

main()内に記述されているとのことですので、たぶん、
Form1.pictureBox1.Image=Image.FromFile("motion1.png");
Application.Run(new Form1());
と書いているのではないでしょうか?

連載 改訂版 C#入門 第3章 クラスとインスタンス
http://www.atmarkit.co.jp/fdotnet/csharp_abc2/csabc2_003/cs2_003_01.html#cs0302

ここであるように、オブジェクト指向にはクラスとインスタンスという概念があります。
今のコードでは、Form1クラスを操作しようとしているのでそのようなエラーが出ます。

具...続きを読む

QC# インスタンスの破棄

C#でインスタンスの破棄を明示的に行いたいのですが、
実際の開発現場では、どのように行っているのでしょうか?

自分で調べると「ガベージコレクタ」が暗黙的に行っているようですが明示的には行わないのが普通なのでしょうか?
もしくは、「Dispose」を使用して明示的に行うのが普通なのでしょうか?

実際に開発されている方からすると簡単な事かもしれませんが教えて頂けると助かります。

以上ですが、よろしくお願いいたします。

Aベストアンサー

結論から言うと、どちらでも良いです。
できれば生成から破棄まで考えて開発できると良いですね。

ガベージコレクションが実行されることで自動開放されますから、
一切.close()や.dispose()を使わなかったとしてもプログラムが
不正終了してしまう事はほとんどありません。

実際の開発では使わなくなったものを使わなくなった時点で
明示的に破棄することが多いです。正確には明示的に破棄するもの、
明示的に破棄しないもの、の2種類に分類しています。

例えばファイルを読み書きするストリーム系のオブジェクトや
データベースとのコネクションなどです。これは開発会社や
開発チーム、案件によって若干違っていて、徹底するところや
適当なところもあります。個人的には徹底したい派ですが。。。

ガベージコレクションが発生するとプログラムの実行動作が
遅くなり、また瞬間的に大きな負担がかかることがあります。
そのため全てをガベージコレクタに任せるのではなく、
明示的に開放できるもの、メモリを大量に消費するものは
その都度、適切に開放していくことで処理効率が良くなります。

プログラミング関連の調べ物で、サンプルソース等を見ることが
あるかと思います。この時サンプルで明示的に開放していたら、
それは明示的に開放したほうが良いもの、と思いましょう。
これだけでもステップアップになりますね。

結論から言うと、どちらでも良いです。
できれば生成から破棄まで考えて開発できると良いですね。

ガベージコレクションが実行されることで自動開放されますから、
一切.close()や.dispose()を使わなかったとしてもプログラムが
不正終了してしまう事はほとんどありません。

実際の開発では使わなくなったものを使わなくなった時点で
明示的に破棄することが多いです。正確には明示的に破棄するもの、
明示的に破棄しないもの、の2種類に分類しています。

例えばファイルを読み書きするストリーム...続きを読む

QC# 子のコントロールからイベントを送る方法?

毎度お世話になっております。

何の手も加えていないフォームに自分で作った
ユーザコントロールを張り付け、そのコントロールからイベントが
発生したら、親フォームを閉じるようにしたいと思っています。

下記にサンプルを記述します。

フォーム側(using文、Designer文は省略)

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private string[] stLines =
{
"こんにちは。",
"こんばんは。",
"おはよう。",
"さようなら。",
"おやすみなさい。",
};
public Form1()
{
InitializeComponent();  // 省略

JLabel j = new JLabel(stLines);
j.Dock = DockStyle.Fill;
this.Controls.Add(j);
}
}
}

ユーザコントロール側(Labelを継承)

namespace WindowsFormsApplication1
{
public class JLabel : Label
{
private string[] stLines = null;
private int lineNo = 0;

public JLabel(string[] Lines)
{
this.Click += new System.EventHandler(this.Jlabel_Click);
this.stLines = Lines;
this.lineNo = 0;
}
private void Jlabel_Click(object sender, EventArgs e)
{
this.lineNo++;
if (this.stLines.Length > this.lineNo)
{
this.Text = this.stLines[this.lineNo];
}
else
{
//ここでイベントを発生させたい
//this.lineNo = 0;
}
}
}
}

上記のように、渡された文字列をもとに、クリックするごとに次の行を
表示するプログラムですが、行番号が行数を超えた場合にイベントを
発生させて、それを親のフォームが監視し、受け取った際にフォームを
閉じるといった処理をさせたいのです。

親のフォームにクリックイベントを仕掛ければ楽ではありますが、
子供のコントロールからの信号を、親が受け取る…といった流れにしたいのです。

以上、よろしくお願いいたします。

毎度お世話になっております。

何の手も加えていないフォームに自分で作った
ユーザコントロールを張り付け、そのコントロールからイベントが
発生したら、親フォームを閉じるようにしたいと思っています。

下記にサンプルを記述します。

フォーム側(using文、Designer文は省略)

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private string[] stLines =
{
"こんにちは。",
"こんばんは。",
"おはよう。",
...続きを読む

Aベストアンサー

C#の文法書を読めば,イベントの作成方法は書いていませんか。

推奨される手順は,次のような感じでしょうか。
・イベントをメンバーとして定義する
public event EventHandler Foo;
・イベントを呼び出すメソッドを定義する
protected virtual void OnFoo (EventArgs e)
{
if (Foo != null)
{
Foo(this, e);
}
}
あとは,イベントを発生させたいところでOnFooを呼び出せばよいです。
イベント引数に情報を載せたいのであれば,EventArgsを派生させたHogeEventArgsを用意して,
イベントの型をEventHadnler<HogeEventArgs>にします。
ref) http://msdn.microsoft.com/ja-jp/library/vstudio/w369ty8x(v=vs.110).aspx
ref) http://msdn.microsoft.com/ja-jp/library/vstudio/hy3sefw3(v=vs.110).aspx

C#の文法書を読めば,イベントの作成方法は書いていませんか。

推奨される手順は,次のような感じでしょうか。
・イベントをメンバーとして定義する
public event EventHandler Foo;
・イベントを呼び出すメソッドを定義する
protected virtual void OnFoo (EventArgs e)
{
if (Foo != null)
{
Foo(this, e);
}
}
あとは,イベントを発生させたいところでOnFooを呼び出せばよいです。
イベント引数に情報を載せたいのであれば,EventArgsを派生させたHogeEventArgsを用意して,
イベントの型をEventHad...続きを読む

QCloseとDisposeの違い

みなさまこんばんわです。よろしくお願い申し上げます。

VB.NET 2008でコーディングしています。
CloseとDisposeの違いについて教えていただきたいのです。

これらのメソッドは、開いたファイルを閉じるときなどにも使いますが、今回お尋ねするのは、フォームを閉じるとき、しかも、自ら呼び出すとき(Me.Close() と、Me.Dispose() )のみに限ったこととしてお話しさせていただきます。

たとえば、ShowDialog() で呼び出したフォームは、そのフォーム内でMe.Close() しても、プロセスは残り、たとえば、タイマーコントロールのイベントに記述していますと、それは実行され続けます。

これを防ぐために、Me.Dispose() を使います。すると、きれいにプロセスは終了し、イベントは発生しない模様です。

そこで、「フォームを閉じる」意味のMe.Close() をすべてMe.Dispose() に変えてしまいました。確実にプロセスを破棄出来ると思ったからです。Webで調べると、違いは「再利用できる、できないの違い」という答えがありましたが、それはきっと、ファイルやオブジェクトのことで、フォームの場合は、再びShowまたはShowDialogで表示させることは可能でしたので、特に問題は感じていませんでした。

ところが、アプリケーション設定で、「最後のフォームを閉じるとき」にアプリケーションがシャットダウンする設定になってるのに、シャットダウンしてくれないことが起こりました。調べてみると、Me.Dispose() が原因。Me.Close() に変えるとうまくいきました。

わけわからなくなってきました。。。

ちなみに、その残ったフォームは、スタートアップフォームであり、別のフォームからShowまたはShowDialogメソッドで呼び出したものではありません。

ここで4つの仮説を立ててみました。

1. ShowDialogで呼び出したフォームは、Me.Dispose()、Showで呼び出した、あるいは、スタートアップフォームは、Me.Close() すれば破棄できる

2. ShowDialogで呼び出したフォームは、Me.Dispose()、スタートアップフォームは、Me.Close()、Showで呼び出したフォームは、どちらでも、破棄できる

3. 呼び出し方ではなく、別の要因が存在する

4. 併記する必要がある場合がある

Me.Close()
Me.Dispose()

または、

Me.Dispose()
Me.Close()



どれが正しいのでしょうか?どなたがご存じの方がいらっしゃいましたら、ご教授いただけませんでしょうか? どうぞよろしくお願い申し上げます。ありがとうございました。

みなさまこんばんわです。よろしくお願い申し上げます。

VB.NET 2008でコーディングしています。
CloseとDisposeの違いについて教えていただきたいのです。

これらのメソッドは、開いたファイルを閉じるときなどにも使いますが、今回お尋ねするのは、フォームを閉じるとき、しかも、自ら呼び出すとき(Me.Close() と、Me.Dispose() )のみに限ったこととしてお話しさせていただきます。

たとえば、ShowDialog() で呼び出したフォームは、そのフォーム内でMe.Close() しても、プロセスは残り、たとえば、...続きを読む

Aベストアンサー

Me.Close()
Me.Dispose()
は根本的に違うものです。

formについて、Close()メソッドはフォームの表示を終了させるメソッドです。

ほかのクラスも同様。すべてのDispose()メソッドについて、これはインスタンスの破棄を明示的に行うものです。

>再利用できる、できないの違い

Dispose()はインスタンスが破棄されるため、再びコンストラクタを用いて、インスタンスを生成しないいけません。

一方Close()はインスタンスが残っているので、それを利用することができます。

>1. ところが、アプリケーション設定で、「最後のフォームを閉じるとき」にアプリケーションがシャットダウンする設定になってるのに、シャットダウンしてくれないことが起こりました。調べてみると、Me.Dispose() が原因。
Me.Close() に変えるとうまくいきました。

通常はどちらでもうまくいきます。

>2. ShowDialogで呼び出したフォームは、Me.Dispose()、スタートアップフォームは、Me.Close()、Showで呼び出したフォームは、どちらでも、破棄できる

ShowDialogの場合は、メソッド内部で、ハンドルが破棄されているため、Close()メソッドの際にDispose()メソッドが呼び出されます。

>3. 呼び出し方ではなく、別の要因が存在する

そう思います。

>4. 併記する必要がある場合がある

インスタンスを明示的に破棄したほうがよい場合は多く存在します。
Disposeが使えるメンバはIDisposableをインターフェースとして持っているメンバです。
これらのメンバは、外部とのやり取りを行うものが多くあります。
たとえばSQLClientに含まれるようなメンバです。

外部とのコネクションを確実に破棄を保障してほしいなどという場合がありますよね、このようなときに使用します。

Using構文を使用するのとまったく同じ理由になります。
正確にはUsing構文を使用できるメンバには条件があります、IDisposableをインターフェースとして持っているメンバに限るというものです。

ほかにもガーベージコレクタによるファイナライズを伴うかどうかという違いがあります。
Disposeの場合はファイナライズが同時に行われるため、使用していたメモリ空間を開放することができます。

上記のような理由により、
Me.Close()
Me.Dispose()
は両方書いたほうがよいと思います。

蛇足ですが、
Me.Dispose()
Me.Close()
はエラーになります。
Me.Dispose()により、Me本体(インスタンス)は削除されてしまいます。
存在しないMeに対してCloseメソッドを要求することはできないためです。

Me.Close()
Me.Dispose()
は根本的に違うものです。

formについて、Close()メソッドはフォームの表示を終了させるメソッドです。

ほかのクラスも同様。すべてのDispose()メソッドについて、これはインスタンスの破棄を明示的に行うものです。

>再利用できる、できないの違い

Dispose()はインスタンスが破棄されるため、再びコンストラクタを用いて、インスタンスを生成しないいけません。

一方Close()はインスタンスが残っているので、それを利用することができます。

>1. ところが、アプリ...続きを読む


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング