アプリ版:「スタンプのみでお礼する」機能のリリースについて

お世話になります。

.NET C#で開発をしている初心者です。
親Form1のReadOnlyにしているtextBox1をダブルクリックしたら、子Form2が表れ、
その中で、ラジオボタンなどで各項目を選択する様になっており、選択した結果の
文字列が、子Form2のReadOnlyにしているtextBox1に表示され、これで良ければ、
決定ボタンであるButton1を押すと、子Form2が閉じられ、元の親Form1のReadOnly
にしているtextBox1に子Form2で決定した文字列が表示される様にしたいのですが、

私がやってうまく行かないのは、子Form2で決定した文字列をClassでsetし、親Form1
に制御が移った時に、classからgetしようとしたのですが、
まず、子Form2が閉じられた時、親Form1はtextBox1にダブルクリックしたままの(後の)
状態、つまりカーソルが残ってる状態で、文字列が表示されない。

子Form2が閉じられた時すぐかもしくは、子Form2の決定ボタンであるButton1を押した
時すぐに親Form1のtextBox1に文字列が表示されていて欲しいのですが、その方法が
分からないので、とりあえず、親Form1のtextBox1のLeaveイベントを発生させて文字列
を表示しています。

どなたかご親切な方、ご教授下さいます様、宜しくお願い申し上げます。

A 回答 (11件中1~10件)

・親フォームのtextBox1の参照を子フォームに持たせておく


・子フォームが閉じられた、あるいはButton1を押したら参照を使って内容を更新
という流れですね。

なお、普通にこれだけ書くと通常設定ではエラーになります。
設定で回避することも不可能ではありませんが、デリゲートを使って親Formのスレッドで書くようにするのが普通です。
http://www.atmarkit.co.jp/fdotnet/dotnettips/312 …
    • good
    • 0
この回答へのお礼

ご回答頂きありがとうございます。

「参照を子フォームに持たせる」、「参照を使って内容を更新」とは
具体的にどの様にすれば良いのでしょうか。

差し支えなければお教え頂きたく宜しくお願いします。

お礼日時:2010/11/20 21:17

まず子フォームのクラスメンバ変数にTextbox型の変数を追加します。


で、子フォームの作成時にでも親フォームから自身のtextBox1を渡してやり、子フォームでは上記メンバ変数に格納します。
上記で受け渡したものは参照として機能し、子フォームから親フォームのtextBox1を任意のタイミングで操作出来るようになります。

……って思ったんですが、よくよく考えると今回は別にtextBox1の参照持ってる必要はないですね。失礼しました。
親フォーム側に文字列型を投げるとtextBox1を変更するパブリックメンバ関数を用意しておいて、その中でデリゲートで処理を委譲するようにして子フォームからこのパブリックメンバ関数を呼べばいいです。

親フォーム側:
class parentForm {
// 記述追加
 delegate ctlFromChild(string str);
 public void changeTextBox1(string str)
 {
  Invoke(new ctlFromChild(changeTextBox1del(str)));
 }
 void changeTextBox1del(string str)
 {
  this.textBox1.text = str;
 }
};

上記処理を追加しておいて、子フォームからは任意のタイミング(質問の場合は子フォームのOnCloseイベントハンドラ中)でparentForm.changeTextBox1を呼び出すことで親のtextBox1が書き換わります。

なんでこう書く必要があるのかは先に提示したURLを読んでください。

なお、複数のテキストボックスを汎用的に扱いたい場合は、最初に言ったように操作対象のコントロールの参照を持っておくとコードが共通化できて見通しが良くなります。
    • good
    • 0
この回答へのお礼

ご丁寧に有難うございます。

しかし、私のスキル不足のよりモジュールエラーが出ており、
何度も申し訳ございませんが、再度ご確認させて頂きたく、
宜しくお願い致します。

確認1
「delegate ctlFromChild(string str);」と
「Invoke(new ctlFromChild(changeTextBox1del(str)));」に
出てくる「ctlFromChild」は、実際の子フォーム名に置き換えて
良いのですよね。

確認2
「Invoke(new ctlFromChild(changeTextBox1del(str)));」
の「(changeTextBox1del(str)」の部分に赤い下波線が出ており、
メソッド名が必要です。と言うモジュールエラーが出てしまっています。
何かが間違い又は不足でしょうか。

確認3
子フォームの呼び出しのコードを下記の様に書いたのですが、
間違ってますでしょうか。「Form1.changeTextBox8(mojiretu)」
と言う所に赤い下波線が出てしまっていて、
「静的でないフィールド、メソッド、またはプロパティに含まれていないため、
コードの解析または生成をサポートしません。」と言うモジュールエラー
が出てしまっているのですが。

string mojiretu;
mojiretu = textBox1.Text;
Form1.changeTextBox8(mojiretu);
↑実際の親フォーム名 ↑実際の親フォームテキストボックス

お礼日時:2010/11/21 11:54

ctlFromChildは「親フォーム内」に定義する「デリゲート」であってクラスではありませんから、「子フォーム名」に置き換えてはいけません。

まぁ同じにしてあれば何かと被らない限りはどんな名前にしてもいいんですが。
#2での提示部分はそのまま使えるように書いたつもりなので、とりあえずは書き換えせずにやってみてください。

一方で「parentForm」については親フォーム名に置き換えてもらっていいというか、置き換えてもらわなければいけません。
    • good
    • 0
この回答へのお礼

お世話になっております。
何度もすみません。

そのまま記述追加致しましたが、

「delegate ctlFormChild(string str);」の「(」カッコの部分と、
「Invoke(new ctlFormChild(change・・・)」の「ctlFormChild」の
部分に赤い下波線が出てモジュールエラーとなってしまいました。

お礼日時:2010/11/23 11:38

あー、すみません、型を忘れてました。


delegate void ctlFromChild(string str);
でどうでしょうか?
    • good
    • 0
この回答へのお礼

お世話になります。今度は、
「Invoke(new ctlFromChild(changeTextBox1del(str)));」
のchangeTextBox1del(str)に赤い下波線が出ていまして、

エラー内容が「静的でないフィールド、メソッド、・・・・で、
オブジェクトが必要です。」と出ています。
私の何かがいけないのでしょうか・・。

お礼日時:2010/11/23 21:03

えーと、私も最近C#を使ってないので色々抜けてるようです。



静的関数ではないためにオブジェクトが要るので、引数changeTextBox1delの頭にthis.を付けてみてください。
それで駄目ならthisの代わりに親フォームの名前を。
    • good
    • 0
この回答へのお礼

お世話になっております。
すみません。先程の「静的な・・・」と言うエラーメッセージ内容は、
子Formの呼び出し側の方でした。
呼び出すメソッド名の頭に、親フォーム名を付けました。そうしましたら、
おそらく親Formの下記記述部分でエラーが出ている為に、
「アクセスできない保護レベルになっています。」と出ました。

親Formの
「Invoke(new ctlFromChild(changeTextBox1del(str)));」
のchangeTextBox1del(str)に赤い下波線が出ていたエラー内容は、
「メソッド名が必要です。」でした。

メソッドと思われていないと言う事でしょうか。

デリゲートって難しいですね。

お礼日時:2010/11/23 22:22

難しいっつーか面倒なだけなんですけどね。



アクセス制限ということなら関数にpublic宣言が入ってないせいかとも思いますが、昨日別解を掘り起こしたので帰宅したらそちらのコードも提示しますね。
まぁ別解とは言っても、デリゲートを使ってるという点では一緒なんですが。
    • good
    • 0

お待たせしました。

別解です。

System.Threadingを使うので、別途using宣言してください。
デリゲート宣言からやりなおします。

private delegate void ctlFromChild();

public void changeTextBox1(string str)
{
 new Thread(new ThreadStart(
  delegate {
   Invoke((ctlFromChild)delegate
   {
    textBox1.Text = str;
   });
 })).Start();
}

動いているコードから引っ張ってきたものなので、これならたぶん大丈夫じゃないかと。
    • good
    • 0
この回答へのお礼

いつもお世話になっております。

「 )がありません。」とエラーが出ていましたので、下記記述

「Invoke((ctlFromChild)(delegate
{
textBox8.Text = str;
});」
の中の最後に「}));」付け足しました。合っていますでしょうか。

また、
「new Thread(new TreadStart(delegate」の「TreadStart」部分に
赤い下波線が有り、「型または名前空間名 'TreadStart' が見つかりません
でした。using ディレクティブまたはアセンブリ参照が不足しています。」
と出ています。

今回「using System.Threading;」は追加しております。
どこが悪いでしょうか。

お礼日時:2010/11/26 07:26

カッコの不足分についてはそれであってます。


というか欠けてましたか、すみません。

> 型または名前空間名 'TreadStart' が見つかりませんでした

先の回答で提示した該当部分は

> new ThreadStart

です。さて何が足りないでしょう?
    • good
    • 0

……って違う。


自力でタイプするのはいいんですが、間違いなくやるようにしてください。

カッコのエラーは、こちらで提示したコードが

> Invoke((ctlFromChild)delegate

であるのに対して、エラーが出ているのは

> Invoke((ctlFromChild)(delegate

となると、delegate前の(を取るのが正しいです。
    • good
    • 0
この回答へのお礼

大変失礼いたしました。

delegate前の(は取りました。

> 型または名前空間名 'TreadStart' が見つかりませんでした

で何が足りないかは、「using System.Threading;」は追加しましたし、

何が足りないんだろう。

すいません、分かりません。

お礼日時:2010/11/27 12:29

んー、#9でもタイプミスを指摘してるんですからそれを疑ってほしかった。


正直このレベルの確認を怠って「何故?」と聞かれるのは非常に悲しいです。

> new T"h"readStart

です。hが足らない。
    • good
    • 0
この回答へのお礼

大変お恥ずかしい限りでございます。
わたしも悲しくなってきました。
hを足した事で、親フォームのエラーはなくなりました。

最初の頃に頂きましたご回答で

>子フォームからは任意のタイミング(質問の場合は子フォームの
>OnCloseイベントハンドラ中)でparentForm.changeTextBox1を
>呼び出すことで親のtextBox1が書き換わります。

こうありましたが、、
子フォームから「 親フォーム名.changeTextBox1」 を呼び出して
もエラー(「静的でないフィールド、メソッド、・・・・で、
オブジェクトが必要です。」)になるのは、
今では記述内容が変わってしまったからでしょうか。

お礼日時:2010/11/27 21:48

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