質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.02%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

静的クラスからメインフォームのコントロールにアクセスする方法が分からない。

dem0nmichik0
dem0nmichik0

総合スコア37

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

4回答

0グッド

1クリップ

1950閲覧

投稿2020/09/22 09:34

編集2020/09/22 10:07

質問のタイトルが間違っていたらすいません。

###実現したいこと
0. 静的クラスからメインフォームにある13個のボタンにアクセスしたい。具体的は,ボタンを押して別フォームを開いたら,メイン画面の13個のボタンを操作不可(Enabledをfalse)にし,フォームを閉じたら,操作有効(Enabledをtrue)にしたい。
0. メインフォームにある13個のボタン,どれかをクリックしたら,他のボタンが押せないようにしたい(ただし,モーダル表示ではなく,モーダレス表示。(画面表示中もほかの画面(13個のボタンではないコントロールをクリックして画面)を開くことがあるから。))

###試したこと
1.サブ・フォームからメイン・フォームのコントロールに値を ...から別フォームクラスからメインフォームクラスにあるコントロールのアクセス方法は,コンストラクタでメインフォームを参照渡しすることで,アクセスできることは分かりました。ですが,現在,開発中のアプリではメインフォームのボタンが13個あるので,上記URLのやり方を取り入れると,変更箇所が多いので,共通関数を作ってそれをコールしたいと考えています。

2.C#でデザインパターンSingletonパターン編 | cloud.config ...を参考に,メインフォームのシングルトンパターンを作成し,静的クラスの共通関数からメインフォームにアクセスできないかと考えたのですが,「Form1.Form1()はアクセスできない保護レベルになっています」とエラーが表示されます。

静的クラス(共通関数)でメインフォームのコントロールは参照できないのでしょうか?どなたかご教授お願いいたします。デザインパターンを絶対使いたいわけではありません。調べていて,1のやり方だとメインフォームの宣言が各フォームでする必要があると思ったので,シングルトンパターンとか使えないかなと思った次第です。

###アプリ実行時の画面
イメージ説明
実際のボタンは13個だけど,練習で3つ

イメージ説明
ソリューションエクスプロー画面

Form1,Form2,Form3,Form4のSize(300, 300)
Button1, 2,3のModifiers(Internal→publicに変更)

###ソース
Program.cs

C#

1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Threading.Tasks; 5using System.Windows.Forms; 6 7namespace WindowsFormsApp1 8{ 9 static class Program 10 { 11 /// <summary> 12 /// アプリケーションのメイン エントリ ポイントです。 13 /// </summary> 14 [STAThread] 15 static void Main() 16 { 17 Application.EnableVisualStyles(); 18 Application.SetCompatibleTextRenderingDefault(false); 19 Application.Run(new Form1()); // ←エラー CS0122 'Form1.Form1()' はアクセスできない保護レベルになっています 20 21 } 22 } 23}

Form1.cs

C#

1using System; 2using System.Collections.Generic; 3using System.ComponentModel; 4using System.Data; 5using System.Drawing; 6using System.Linq; 7using System.Text; 8using System.Threading.Tasks; 9using System.Windows.Forms; 10 11namespace WindowsFormsApp1 12{ 13 public partial class Form1 : Form 14 { 15 internal static Form1 form1; 16 17 // コンストラクタ 18 private Form1() 19 { 20 InitializeComponent(); 21 } 22 23 // シングルトンパターン 24 public static Form1 GetInstance() 25 { 26 if(form1 == null) 27 { 28 form1 = new Form1(); 29 return form1; 30 } 31 return form1; 32 } 33 34 private void button1_Click_1(object sender, EventArgs e) 35 { 36 // 自フォームへの参照を渡す 37 //Form2 f2 = new Form2(this); 38 Form2 f2 = new Form2(); 39 // サブフォームをモーダレス形式で表示 40 f2.Show(); 41 } 42 43 private void button2_Click(object sender, EventArgs e) 44 { 45 // 自フォームへの参照を渡す 46 //Form3 f3 = new Form3(this); 47 Form3 f3 = new Form3(); 48 // サブフォームをモーダレス形式で表示 49 f3.Show(); 50 } 51 52 private void button3_Click(object sender, EventArgs e) 53 { 54 // 自フォームへの参照を渡す 55 //Form4 f3 = new Form4(this); 56 Form4 f3 = new Form4(); 57 // サブフォームをモーダレス形式で表示 58 f3.Show(); 59 } 60 } 61} 62

Form2.cs

C#

1using System; 2using System.Collections.Generic; 3using System.ComponentModel; 4using System.Data; 5using System.Drawing; 6using System.Linq; 7using System.Text; 8using System.Threading.Tasks; 9using System.Windows.Forms; 10 11namespace WindowsFormsApp1 12{ 13 public partial class Form2 : Form 14 { 15 //Form1 f1; 16 17 // コンストラクタ 18 //public Form2(Form1 f) 19 public Form2() 20 { 21 InitializeComponent(); 22 23 // メインフォームの参照を保存 24 //f1 = f; 25 } 26 27 private void Form2_Load(object sender, EventArgs e) 28 { 29 //f1.button1.Enabled = false; 30 //f1.button2.Enabled = false; 31 //f1.button3.Enabled = false; 32 Common.SetButtonEnabled(false); 33 } 34 35 private void Form2_FormClosed(object sender, FormClosedEventArgs e) 36 { 37 //f1.button1.Enabled = true; 38 //f1.button2.Enabled = true; 39 //f1.button3.Enabled = true; 40 Common.SetButtonEnabled(true); 41 } 42 } 43} 44

Form3.cs

C#

1using System; 2using System.Collections.Generic; 3using System.ComponentModel; 4using System.Data; 5using System.Drawing; 6using System.Linq; 7using System.Text; 8using System.Threading.Tasks; 9using System.Windows.Forms; 10 11namespace WindowsFormsApp1 12{ 13 public partial class Form3 : Form 14 { 15 //Form1 f1; 16 17 //public Form3(Form1 f) 18 public Form3() 19 { 20 InitializeComponent(); 21 22 //// メインフォームの参照を保存 23 //f1 = f; 24 } 25 26 private void Form3_Load(object sender, EventArgs e) 27 { 28 //f1.button1.Enabled = false; 29 //f1.button2.Enabled = false; 30 //f1.button3.Enabled = false; 31 Common.SetButtonEnabled(false); 32 } 33 34 private void Form3_FormClosed(object sender, FormClosedEventArgs e) 35 { 36 //f1.button1.Enabled = true; 37 //f1.button2.Enabled = true; 38 //f1.button3.Enabled = true; 39 Common.SetButtonEnabled(true); 40 } 41 } 42} 43

Form4.cs

C#

1using System; 2using System.Collections.Generic; 3using System.ComponentModel; 4using System.Data; 5using System.Drawing; 6using System.Linq; 7using System.Text; 8using System.Threading.Tasks; 9using System.Windows.Forms; 10 11namespace WindowsFormsApp1 12{ 13 public partial class Form4 : Form 14 { 15 //Form1 f1; 16 17 //public Form4(Form1 f) 18 public Form4() 19 { 20 InitializeComponent(); 21 } 22 23 private void Form4_Load(object sender, EventArgs e) 24 { 25 //f1.button1.Enabled = false; 26 //f1.button2.Enabled = false; 27 //f1.button3.Enabled = false; 28 Common.SetButtonEnabled(false); 29 } 30 31 private void Form4_FormClosed(object sender, FormClosedEventArgs e) 32 { 33 //f1.button1.Enabled = true; 34 //f1.button2.Enabled = true; 35 //f1.button3.Enabled = true; 36 Common.SetButtonEnabled(true); 37 } 38 } 39} 40

Common.cs

C#

1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5using System.Threading.Tasks; 6 7namespace WindowsFormsApp1 8{ 9 public static partial class Common 10 { 11 public static void SetButtonEnabled(bool flg) 12 { 13 var form = Form1.GetInstance(); 14 15 form.button1.Enabled = flg; 16 form.button2.Enabled = flg; 17 form.button3.Enabled = flg; 18 } 19 } 20} 21

###開発環境
OS:Windows7 64bit
IDE:Visual Studio Professional2017

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

gentaro

2020/09/22 10:25 編集

ちょっとピントがずれてたので削除
dodox86

2020/09/22 10:00

質問への直接的な回答ではないのかもしれませんけど、メインフォームであるForm1に13個のボタンとフォームを制御するパブリックメソッドを用意して、それを操作するようなかたちではダメなのでしょうか?

回答4

2

Application.Run(Form1.GetInstance());
こうしてください。


今の状況というか問題点は、

  1. メインフォームとサブフォーム1-13は既にできていて、動作自体に問題はない
  2. サブフォームを排他的(どれか一つだけしか開けないよう)に改造しようとしている
  3. その際地道にやれば(コメントアウトのコード)できることはわかっている
  4. しかし13個はだるいし、もっといい方法がありそうに思える

ってことですよね?(実際2個目くらいでもうだるかったです^^;

自分だったらこうするかなぁ?ってコードです。
button1_Clickもまとめてもよさそうですが、行数も減りそうにないのでそのまま。

Form1.cs

C#

1using System; 2using System.Drawing; 3using System.Windows.Forms; 4 5namespace Questions293390 6{ 7 public partial class Form1 : Form 8 { 9 // シングルトンの必要はないかもしれないが、どうせSubFormからForm1をいじりたくなりますよね? 10 public static Form1 Instance { get; } = new Form1(); 11 12 private Form1() => InitializeComponent(); 13 14 private void button1_Click(object sender, EventArgs e) 15 => ShowSubForm(new SubForm1(), panel1); 16 17 private void button2_Click(object sender, EventArgs e) 18 => ShowSubForm(new SubForm2(), panel1); 19 20 private void button3_Click(object sender, EventArgs e) 21 => ShowSubForm(new SubForm3(), panel1); 22 23 // class Commonにあっても別に構わない 24 private static void ShowSubForm(Form subForm, Panel group) 25 { 26 // Panel配下のボタンを不活性 27 foreach(var control in group.Controls) 28 { 29 if(control is Button button) 30 button.Enabled = false; 31 } 32 33 // SubFormのクローズを購読 34 subForm.FormClosed += SubForm_FormClosed; 35 // PanelをTagに入れて覚えておく 36 subForm.Tag = group; 37 subForm.Show(); 38 } 39 40 // クローズ時にPanel配下のボタンを戻す 41 private static void SubForm_FormClosed(object sender, FormClosedEventArgs e) 42 { 43 // senderはSubForm自身 44 if(sender is Form subForm) 45 { 46 // PanelをTagから取り出す 47 if(subForm.Tag is Panel group) 48 { 49 foreach(var control in group.Controls) 50 { 51 if(control is Button button) 52 button.Enabled = true; 53 } 54 } 55 } 56 } 57 } 58 59 // SubFormではFormClosed等のイベントを書く必要がなくて楽々という意味 60 // 実際は普通に作る 61 public class SubForm1 : Form 62 { 63 public SubForm1() { Text = "SubForm1"; ClientSize = new Size(300, 200); } 64 } 65 public class SubForm2 : Form 66 { 67 public SubForm2() { Text = "SubForm2"; ClientSize = new Size(300, 200); } 68 } 69 public class SubForm3 : Form 70 { 71 public SubForm3() { Text = "SubForm3"; ClientSize = new Size(300, 200); } 72 } 73}

Form1.Designer.cs

C#

1namespace Questions293390 2{ 3 partial class Form1 4 { 5 /// <summary> 6 /// 必要なデザイナー変数です。 7 /// </summary> 8 private System.ComponentModel.IContainer components = null; 9 10 /// <summary> 11 /// 使用中のリソースをすべてクリーンアップします。 12 /// </summary> 13 /// <param name="disposing">マネージド リソースを破棄する場合は true を指定し、その他の場合は false を指定します。</param> 14 protected override void Dispose(bool disposing) 15 { 16 if(disposing && (components != null)) 17 { 18 components.Dispose(); 19 } 20 base.Dispose(disposing); 21 } 22 23 #region Windows フォーム デザイナーで生成されたコード 24 25 /// <summary> 26 /// デザイナー サポートに必要なメソッドです。このメソッドの内容を 27 /// コード エディターで変更しないでください。 28 /// </summary> 29 private void InitializeComponent() 30 { 31 this.button1 = new System.Windows.Forms.Button(); 32 this.button2 = new System.Windows.Forms.Button(); 33 this.button3 = new System.Windows.Forms.Button(); 34 this.panel1 = new System.Windows.Forms.Panel(); 35 this.otherButton = new System.Windows.Forms.Button(); 36 this.label1 = new System.Windows.Forms.Label(); 37 this.panel1.SuspendLayout(); 38 this.SuspendLayout(); 39 // 40 // button1 41 // 42 this.button1.Location = new System.Drawing.Point(5, 34); 43 this.button1.Name = "button1"; 44 this.button1.Size = new System.Drawing.Size(75, 23); 45 this.button1.TabIndex = 0; 46 this.button1.Text = "button1"; 47 this.button1.UseVisualStyleBackColor = true; 48 this.button1.Click += new System.EventHandler(this.button1_Click); 49 // 50 // button2 51 // 52 this.button2.Location = new System.Drawing.Point(5, 63); 53 this.button2.Name = "button2"; 54 this.button2.Size = new System.Drawing.Size(75, 23); 55 this.button2.TabIndex = 1; 56 this.button2.Text = "button2"; 57 this.button2.UseVisualStyleBackColor = true; 58 this.button2.Click += new System.EventHandler(this.button2_Click); 59 // 60 // button3 61 // 62 this.button3.Location = new System.Drawing.Point(5, 92); 63 this.button3.Name = "button3"; 64 this.button3.Size = new System.Drawing.Size(75, 23); 65 this.button3.TabIndex = 2; 66 this.button3.Text = "button3"; 67 this.button3.UseVisualStyleBackColor = true; 68 this.button3.Click += new System.EventHandler(this.button3_Click); 69 // 70 // panel1 71 // 72 this.panel1.Controls.Add(this.label1); 73 this.panel1.Controls.Add(this.button3); 74 this.panel1.Controls.Add(this.button1); 75 this.panel1.Controls.Add(this.button2); 76 this.panel1.Location = new System.Drawing.Point(153, 136); 77 this.panel1.Name = "panel1"; 78 this.panel1.Size = new System.Drawing.Size(112, 125); 79 this.panel1.TabIndex = 3; 80 // 81 // otherButton 82 // 83 this.otherButton.Location = new System.Drawing.Point(538, 54); 84 this.otherButton.Name = "otherButton"; 85 this.otherButton.Size = new System.Drawing.Size(75, 23); 86 this.otherButton.TabIndex = 4; 87 this.otherButton.Text = "otherButton"; 88 this.otherButton.UseVisualStyleBackColor = true; 89 // 90 // label1 91 // 92 this.label1.AutoSize = true; 93 this.label1.Location = new System.Drawing.Point(3, 10); 94 this.label1.Name = "label1"; 95 this.label1.Size = new System.Drawing.Size(35, 12); 96 this.label1.TabIndex = 3; 97 this.label1.Text = "label1"; 98 // 99 // Form1 100 // 101 this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); 102 this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 103 this.ClientSize = new System.Drawing.Size(800, 450); 104 this.Controls.Add(this.otherButton); 105 this.Controls.Add(this.panel1); 106 this.Name = "Form1"; 107 this.Text = "Form1"; 108 this.panel1.ResumeLayout(false); 109 this.panel1.PerformLayout(); 110 this.ResumeLayout(false); 111 112 } 113 114 #endregion 115 private System.Windows.Forms.Label label1; 116 private System.Windows.Forms.Button otherButton; 117 private System.Windows.Forms.Button button1; 118 private System.Windows.Forms.Button button2; 119 private System.Windows.Forms.Button button3; 120 private System.Windows.Forms.Panel panel1; 121 } 122}

Program.cs

C#

1using System; 2using System.Windows.Forms; 3 4namespace Questions293390 5{ 6 static class Program 7 { 8 [STAThread] 9 static void Main() 10 { 11 Application.EnableVisualStyles(); 12 Application.SetCompatibleTextRenderingDefault(false); 13 Application.Run(Form1.Instance); 14 } 15 } 16}

投稿2020/09/22 10:07

編集2020/09/27 08:30
TN8001

総合スコア8053

Zuishin, dem0nmichik0👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

dem0nmichik0

2020/09/22 17:01

TN8001様,回答ありがとうございます。 ご指摘のように,修正したら動きました。ありがとうございます。
dem0nmichik0

2020/09/24 14:56 編集

TN8001様,回答ありがとうございます。 >1. メインフォームとサブフォーム1-13は既にできていて、動作自体に問題はない >2. サブフォームを排他的(どれか一つだけしか開けないよう)に改造しようとしている >3. その際地道にやれば(コメントアウトのコード)できることはわかっている >4. しかし13個はだるいし、もっといい方法がありそうに思える その通りです。 本日,教えていただいたソースコードを打ち込んでみて,ソースコードを理解している最中です。 C#はコード歴が短く,ラムダ式(=>)やデリゲートを全然理解していないことがわかったので勉強しなおします。1点教えてください。 ・ShowSubForm()メソッドの中にClosed()がありますが,Closed()はメソッドでしょうか?イベントハンドラーでしょうか?今まで,メソッドの中にメソッドがあるのを見たことがなくてネットで調べるときの用語を教えていただけますか?
TN8001

2020/09/24 15:46 編集

void Closed(object sender, FormClosedEventArgs e) のとこですね? それは「ローカル関数」です。 [ローカル関数 - C# プログラミング ガイド | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/classes-and-structs/local-functions そのメソッド内だけで使える関数です。 そして subForm.FormClosed += Closed; としていることを見ればわかりますが、「イベントハンドラー」でもあります。 よく button1.Click += new EventHandler(button1_Click); private void button1_Click(object sender, EventArgs e){ } のようなのがありますが、あれ(button1_Click)と同じです。 なぜこのような一見面倒なことをしているかというと、Closed()の中でsubForm・group変数を使いたかったためです(subFormはsenderを使えばいいですが、groupをほかの方法で渡すのはなかなか難しいです) [ローカル変数の捕獲 - C# によるプログラミング入門 | ++C++; // 未確認飛行 C](https://ufcpp.net/study/csharp/functional/fun_localfunctions/#capture-local うまく説明できてる気がしませんが、伝わりますでしょうか?^^;
dem0nmichik0

2020/09/27 06:57

TN8001様、回答ありがとうございます。 >void Closed(object sender, FormClosedEventArgs e)のとこですね? そうです。 >それは「ローカル関数」です。メソッド内だけで使える関数なんてのもあるんですね。 >なぜこのような一見面倒なことをしているかというと、Closed()の中でsubForm・group変数を使いた>かったためです(subFormはsenderを使えばいいですが、groupをほかの方法で渡すのはなかなか難し>いです) すいません、私自身のレベルが低く難しさがわからないです。理解できるようにもっと勉強します。 このたびはありがとうございました。
TN8001

2020/09/27 08:30

凝ったことをやめました^^; これならご理解いただけるでしょう。 SubFormでTagを使っていないと断定し、Form1で好きに使ってしまう。 ノイズになっていそうなのでイベント解除を省略(この場合はリークしないはず) [【雑記】イベントの購読とその解除 - C# によるプログラミング入門 | ++C++; // 未確認飛行 C](https://ufcpp.net/study/csharp/MiscEventSubscribe.html#must-unsubscribe 上記のような条件を付けずに汎用的な定型パターンが元のコードというわけです。
dem0nmichik0

2020/09/27 10:58

TN8001様、回答の編集ありがとうございます。 >凝ったことをやめました^^; これならご理解いただけるでしょう。 >SubFormでTagを使っていないと断定し、Form1で好きに使ってしまう。 はい、これは分かります。object型のTagプロパティにPanel型のgroup変数をセットすることで、SubForm_FormClosed()メソッドの中でgroup変数を使えるようにしているのですね。 確かに、ローカル変数を知らないと、is演算子を使ったこのような書き方になりますね。 先に教えていただいたローカル関数を使ったコードとこのis演算子を使ったコードでは、後者のほうが、 ・条件文が多い。 ・行数が多い。 ・使わなくてもいいプロパティ(Tag)を使っている。 など、ローカル関数を使ったコードのほうが良いと分かりました。 丁寧に教えていただきありがとうございました。

1

ベストアンサー

「Form1にボタンが13個とかあって,それをあるタイミングで有効化/無効化しないとならない」というForm1側の実装の詳細や都合を,
他のForm(Form2とか)がわざわざ知る必要はない.
Form1側からすれば,単に子Formが閉じたタイミングさえ教えてもらえるならば,そこらへん(ボタンをどうこうすること)は自身でやれば良いのではないだろうか.

よって,例えば,こんなinterfaceを用意して,子Formがこれを実装することにしてはどうか.
これで子Formのやるべきこと(責任)がはっきりする.

public delegate void AtClosed_Deleg(); //子フォーム用 interface IChildForm { //子フォームをModeless表示する. //引数Callbackがnullでない場合には,子フォームは自身が閉じた際にCallbackを呼ぶ. void ShowModeless( AtClosed_Deleg Callback ); }

例えば子フォームはこんな感じに実装するかもしれない.

//Form2 public partial class Form2 : Form, IChildForm { //--- //IChildFormの実装 public void ShowModeless( AtClosed_Deleg Callback ) { m_CallbackAtClosed = Callback; this.Show(); } //--- //具体実装 private AtClosed_Deleg m_CallbackAtClosed; private void Form2_FormClosed( object sender, FormClosedEventArgs e ) { if( m_CallbackAtClosed != null ){ m_CallbackAtClosed(); } } }

Form1側の例:

//子フォーム表示用のボタンのイベント //(この例は,Form2を作ってそれを表示している.他の子フォーム用のボタンに関しても同様に書く) private void button1_Click( object sender, EventArgs e ){ ShowChildForm( new Form2() ); } //子フォームの表示作業 private void ShowChildForm( IChildForm Child ) { EnableButton( false ); //子フォームの表示前にボタンをDisable Child.ShowModeless( ()=>{ EnableButton(true); } ); } //ボタンのEnable/Disable //(この例ではbutton1だけを扱っているが,実際は13個のボタンを扱う) private void EnableButton( bool Enable ){ button1.Enabled = Enable; }

Singletonとかstaticとかは全く不要に思う.

投稿2020/09/23 09:38

編集2020/09/23 09:50
fana

総合スコア10672

dem0nmichik0👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

dem0nmichik0

2020/09/26 08:11 編集

fana様、回答ありがとうございます。 >Form1側からすれば,単に子Formが閉じたタイミングさえ教えてもらえるならば,そこらへん(ボタンを>どうこうすること)は自身でやれば良いのではないだろうか. 確かにその通りです。自分のレベルだと子Formが閉じたタイミングをどうやって知るかわからなかったので、子フォームからメインフォームにアクセスできるメソッドを作成したほうが楽かなと思ったから質問のようになりました。 遅くなりましたが、本日、ソースコードを打ち込んでみて、動作を確認しました。現状、メインフォームおよびサブフォーム1-13は動作していて、メインフォームのボタンクリック時にサブフォームを排他的にしようと改造しているので、この方法が楽だと思いました。 下記、いくつか教えてください。 1.このコードを理解するにはラムダ式およびデリゲートを十分に理解している必要がありますか?私自身、C#はレベルが低く、用語を知っているくらいで、コーディングするときもネットで調べてコピーすることが多いので、ラムダ式やデリゲートを十分に理解していないとわからないのであれば、勉強します。 2.1つ目のソースコードのデリゲート宣言とインターフェースは、どこに記述するのが一般的ですか?試してみた限りではForm1やForm2のnamespace先頭とかであれば問題はなかったのですが。 3.1に関係するかもしれないのですが、 「private void button1_Click(object sender, EventArgs e) => ShowSubForm(new SubForm1(), panel1);」 のようなラムダ式を使ったコードは見たことがあるのですが、 「Child.ShowModeless( ()=>{ EnableButton(true); } );」 のようにShowModelessメソッドの引数にラムダ式を使ったコード(上記)は見たことがありません。さらに左辺()の中が空白というのも見たことがありません。これはラムダ式やデリゲートを理解すればわかりますか? 申し訳ありませんが、ご教授お願いいたします。
fana

2020/09/26 08:41

> 1 回答の趣旨は,delegateやラムダを使うことではなく, Form1の実装上の都合はForm1が扱えばよい.「ボタンを何個も持っていてそれらを特定のタイミングでDisableにする必要がある」などという具体的な話をForm1の外側に知らせる必要は無い. ただし,残念ながら処理タイミングがForm1だけでは把握できない様子なので,ならば,(仕方ないので)「そのタイミングだけは伝達してもらう」ことにする. …といった事柄(考え方)です. (コード例では IChildForm.ShowModeless()の引数をdelegateとし,そこにForm1側からラムダ式を渡しているが,この実装形態自体は単なる例でしかない.) > 2 それ用のソースファイルを1つ用意してそこに書けばよいでしょう. > 3 これは言語文法的な話なので,勉強するしかないですね.
dem0nmichik0

2020/09/26 09:04

fana様、早い回答ありがとうございます。 >Form1の実装上の都合はForm1が扱えばよい.「ボタンを何個も持っていてそれらを特定のタイミングで>Disableにする必要がある」などという具体的な話をForm1の外側に知らせる必要は無い. >ただし,残念ながら処理タイミングがForm1だけでは把握できない様子なので,ならば,(仕方ないので)>「そのタイミングだけは伝達してもらう」ことにする. > >…といった事柄(考え方)です なるほど、「タイミングを伝達してもらう」という考え方が重要なんですね。そして、その一つのコード例として「引数にdelegateとし、そこにForm1側からラムダ式を渡す」という方法があることを知り、とても勉強になりました。 >それ用のソースファイルを1つ用意してそこに書けばよいでしょう. 分かりました。 >これは言語文法的な話なので,勉強するしかないですね. はい、勉強します。 このたびはありがとうございました。

0

とりあえずエラーを治したいのなら

diff

1namespace WindowsFormsApp1 2{ 3 public partial class Form1 : Form 4 { 5 internal static Form1 form1; 6 7 // コンストラクタ 8- private Form1() 9+ public Form1() 10 { 11 InitializeComponent(); 12 }

追記

メインフォームのシングルトンパターンを作成し,静的クラスの共通関数からメインフォームにアクセスできないかと考えたのですが

無意味です。
シングルトンはインスタンスが一つであることを保証するだけです。
そもそもWinFormsの標準テンプレートでメインフォームとなる画面はProgram.csの

csharp

1 Application.Run(new Form1());

の部分で生成されるものが一つだけで、わざわざコンストラクタを呼び出して同じ画面のインスタンスを作成するようなプログラムでなければ、シングルトンにするまでもなく一つしかありません。

メインフォームのボタンが13個あるので,上記URLのやり方を取り入れると,変更箇所が多いので,共通関数を作ってそれをコールしたいと考えています。

ボタンが何個あろうと、Form.Controlsプロパティにからそのフォームの子コントロールを全て取得できるので

csharp

1 foreach (Control c in this.Controls) 2 { 3 if (c is Button b) 4 b.Enabled = false; 5 }

こういうコードを書けば「その画面上の全てのボタン」のプロパティは変更できます。

投稿2020/09/22 10:14

編集2020/09/22 10:22
gentaro

総合スコア8943

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

dem0nmichik0

2020/09/22 17:09

gentaro様,回答ありがとうございます。 >わざわざコンストラクタを呼び出して同じ画面のインスタンスを作成するようなプログラムでなければ、シ>ングルトンにするまでもなく一つしかありません。 確かにその通りです。すいません,各クラスにメインフォームを参照渡しすると,各クラスにメインフォームを宣言する(Form1 f1;)ので,複数のインスタンスがあると勘違いしていました。 foreach (Control c in this.Controls) { if (c is Button b) b.Enabled = false; } はどこに記述すればよいのでしょうか?ご教授お願いいたします。
gentaro

2020/09/22 22:09

> 各クラスにメインフォームを宣言する コメントアウトされているコードを見る限り、ただForm1のインスタンスへの参照を保持するだけであれば、インスタンスそのものは1つです。 > どこに記述すれば Commonというクラスを廃止し、そこでやっている処理の代わりにForm1にこういった処理をするメソッドを定義してpublicで定義していれば、Form1への参照を持っている各サブフォームからそのメソッドを呼ぶだけでいいです。
dem0nmichik0

2020/09/26 06:07

gentaro様、回答ありがとうございます。 ご指摘のようにCommonクラスを削除し、Form1にPublicメソッドを作り、その中に記述して各フォームからコールしたらできました。このたびはありがとうございました。

0

質問の主旨がよく分からないですが、、、、

例えば、

form.button1.Enabled = flg;

これがエラーになる、ということでしょうか?
(多分、そんな気が、、。違ったら、無視してください)
Form1は、別スレッドで動いているので、直接、フォーム上のコントロールにアクセスはできません。 Form1 に、アクセス用メソッドを作成し、それを呼び出します。
その中で、Invoke((Action)(() => button1.Enabled = true)); のようにコントロール制御を行う。 (他にも方法はありますが)

また、

静的クラスからメインフォーム

は、普通にアクセスできます。ただ、上記のように、ファーム上のコントロールを直接、アクセスできないだけです。

投稿2020/09/22 09:59

pepperleaf

総合スコア6379

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

2020/09/22 12:44

こちらの回答が他のユーザーから「過去の低評価」という指摘を受けました。

回答へのコメント

gentaro

2020/09/22 10:08

> Form1は、別スレッドで動いているので、直接、フォーム上のコントロールにアクセスはできません。 このソースのどこでスレッドが生成されていますか? 全部UIスレッドで動いてると思いますが。
pepperleaf

2020/09/22 11:03

Form1は、、と言うのは正確ではないかもですが、 UIスレッドは確かですが、Form毎の UIスレッドじゃないですか? Commonから、見ると別では?
gentaro

2020/09/22 12:44

C#ではThreadクラスやTaskクラス、async/await等を使って別スレッドでの処理が可能ですが、このソース上どこにそういった処理がありますか?
pepperleaf

2020/09/22 23:12

ちょっと外してみたいですね。

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.02%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。