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

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

ただいまの
回答率

87.59%

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

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,077

score 36

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

実現したいこと

  1. 静的クラスからメインフォームにある13個のボタンにアクセスしたい。具体的は,ボタンを押して別フォームを開いたら,メイン画面の13個のボタンを操作不可(Enabledをfalse)にし,フォームを閉じたら,操作有効(Enabledをtrue)にしたい。
  2. メインフォームにある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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    static class Program
    {
        /// <summary>
        /// アプリケーションのメイン エントリ ポイントです。
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());     // ←エラー CS0122  'Form1.Form1()' はアクセスできない保護レベルになっています

        }
    }
}

Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        internal static Form1 form1;

        // コンストラクタ
        private Form1()
        {
            InitializeComponent();
        }

        // シングルトンパターン
        public static Form1 GetInstance()
        {
            if(form1 == null)
            {
                form1 = new Form1();
                return form1;
            }
            return form1;
        }

        private void button1_Click_1(object sender, EventArgs e)
        {
            // 自フォームへの参照を渡す
            //Form2 f2 = new Form2(this);
            Form2 f2 = new Form2();
            // サブフォームをモーダレス形式で表示
            f2.Show();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            // 自フォームへの参照を渡す
            //Form3 f3 = new Form3(this);
            Form3 f3 = new Form3();
            // サブフォームをモーダレス形式で表示
            f3.Show();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            // 自フォームへの参照を渡す
            //Form4 f3 = new Form4(this);
            Form4 f3 = new Form4();
            // サブフォームをモーダレス形式で表示
            f3.Show();
        }
    }
}


Form2.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form2 : Form
    {
        //Form1 f1;

        // コンストラクタ
        //public Form2(Form1 f)
        public Form2()
        {
            InitializeComponent();

            // メインフォームの参照を保存
            //f1 = f;
        }

        private void Form2_Load(object sender, EventArgs e)
        {
            //f1.button1.Enabled = false;
            //f1.button2.Enabled = false;
            //f1.button3.Enabled = false;
            Common.SetButtonEnabled(false);
        }

        private void Form2_FormClosed(object sender, FormClosedEventArgs e)
        {
            //f1.button1.Enabled = true;
            //f1.button2.Enabled = true;
            //f1.button3.Enabled = true;
            Common.SetButtonEnabled(true);
        }
    }
}


Form3.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form3 : Form
    {
        //Form1 f1;

        //public Form3(Form1 f)
        public Form3()
        {
            InitializeComponent();

            //// メインフォームの参照を保存
            //f1 = f;
        }

        private void Form3_Load(object sender, EventArgs e)
        {
            //f1.button1.Enabled = false;
            //f1.button2.Enabled = false;
            //f1.button3.Enabled = false;
            Common.SetButtonEnabled(false);
        }

        private void Form3_FormClosed(object sender, FormClosedEventArgs e)
        {
            //f1.button1.Enabled = true;
            //f1.button2.Enabled = true;
            //f1.button3.Enabled = true;
            Common.SetButtonEnabled(true);
        }
    }
}


Form4.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form4 : Form
    {
        //Form1 f1;

        //public Form4(Form1 f)
        public Form4()
        {
            InitializeComponent();
        }

        private void Form4_Load(object sender, EventArgs e)
        {
            //f1.button1.Enabled = false;
            //f1.button2.Enabled = false;
            //f1.button3.Enabled = false;
            Common.SetButtonEnabled(false);
        }

        private void Form4_FormClosed(object sender, FormClosedEventArgs e)
        {
            //f1.button1.Enabled = true;
            //f1.button2.Enabled = true;
            //f1.button3.Enabled = true;
            Common.SetButtonEnabled(true);
        }
    }
}


Common.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WindowsFormsApp1
{
    public static partial class Common
    {
        public static void SetButtonEnabled(bool flg)
        {
            var form = Form1.GetInstance();

            form.button1.Enabled = flg;
            form.button2.Enabled = flg;
            form.button3.Enabled = flg;
        }
    }
}

開発環境

OS:Windows7 64bit
IDE:Visual Studio Professional2017

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

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

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

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • gentaro

    2020/09/22 18:47 編集

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

    キャンセル

  • dodox86

    2020/09/22 19:00

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

    キャンセル

回答 4

+2

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


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

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

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

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

Form1.cs

using System;
using System.Drawing;
using System.Windows.Forms;

namespace Questions293390
{
    public partial class Form1 : Form
    {
        // シングルトンの必要はないかもしれないが、どうせSubFormからForm1をいじりたくなりますよね?
        public static Form1 Instance { get; } = new Form1();

        private Form1() => InitializeComponent();

        private void button1_Click(object sender, EventArgs e)
            => ShowSubForm(new SubForm1(), panel1);

        private void button2_Click(object sender, EventArgs e)
            => ShowSubForm(new SubForm2(), panel1);

        private void button3_Click(object sender, EventArgs e)
            => ShowSubForm(new SubForm3(), panel1);

        // class Commonにあっても別に構わない
        private static void ShowSubForm(Form subForm, Panel group)
        {
            // Panel配下のボタンを不活性
            foreach(var control in group.Controls)
            {
                if(control is Button button)
                    button.Enabled = false;
            }

            // SubFormのクローズを購読
            subForm.FormClosed += SubForm_FormClosed;
            // PanelをTagに入れて覚えておく
            subForm.Tag = group;
            subForm.Show();
        }

        // クローズ時にPanel配下のボタンを戻す
        private static void SubForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            // senderはSubForm自身
            if(sender is Form subForm)
            {
                // PanelをTagから取り出す
                if(subForm.Tag is Panel group)
                {
                    foreach(var control in group.Controls)
                    {
                        if(control is Button button)
                            button.Enabled = true;
                    }
                }
            }
        }
    }

    // SubFormではFormClosed等のイベントを書く必要がなくて楽々という意味
    // 実際は普通に作る
    public class SubForm1 : Form
    {
        public SubForm1() { Text = "SubForm1"; ClientSize = new Size(300, 200); }
    }
    public class SubForm2 : Form
    {
        public SubForm2() { Text = "SubForm2"; ClientSize = new Size(300, 200); }
    }
    public class SubForm3 : Form
    {
        public SubForm3() { Text = "SubForm3"; ClientSize = new Size(300, 200); }
    }
}

Form1.Designer.cs

namespace Questions293390
{
    partial class Form1
    {
        /// <summary>
        /// 必要なデザイナー変数です。
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// 使用中のリソースをすべてクリーンアップします。
        /// </summary>
        /// <param name="disposing">マネージド リソースを破棄する場合は true を指定し、その他の場合は false を指定します。</param>
        protected override void Dispose(bool disposing)
        {
            if(disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows フォーム デザイナーで生成されたコード

        /// <summary>
        /// デザイナー サポートに必要なメソッドです。このメソッドの内容を
        /// コード エディターで変更しないでください。
        /// </summary>
        private void InitializeComponent()
        {
            this.button1 = new System.Windows.Forms.Button();
            this.button2 = new System.Windows.Forms.Button();
            this.button3 = new System.Windows.Forms.Button();
            this.panel1 = new System.Windows.Forms.Panel();
            this.otherButton = new System.Windows.Forms.Button();
            this.label1 = new System.Windows.Forms.Label();
            this.panel1.SuspendLayout();
            this.SuspendLayout();
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(5, 34);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(75, 23);
            this.button1.TabIndex = 0;
            this.button1.Text = "button1";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // button2
            // 
            this.button2.Location = new System.Drawing.Point(5, 63);
            this.button2.Name = "button2";
            this.button2.Size = new System.Drawing.Size(75, 23);
            this.button2.TabIndex = 1;
            this.button2.Text = "button2";
            this.button2.UseVisualStyleBackColor = true;
            this.button2.Click += new System.EventHandler(this.button2_Click);
            // 
            // button3
            // 
            this.button3.Location = new System.Drawing.Point(5, 92);
            this.button3.Name = "button3";
            this.button3.Size = new System.Drawing.Size(75, 23);
            this.button3.TabIndex = 2;
            this.button3.Text = "button3";
            this.button3.UseVisualStyleBackColor = true;
            this.button3.Click += new System.EventHandler(this.button3_Click);
            // 
            // panel1
            // 
            this.panel1.Controls.Add(this.label1);
            this.panel1.Controls.Add(this.button3);
            this.panel1.Controls.Add(this.button1);
            this.panel1.Controls.Add(this.button2);
            this.panel1.Location = new System.Drawing.Point(153, 136);
            this.panel1.Name = "panel1";
            this.panel1.Size = new System.Drawing.Size(112, 125);
            this.panel1.TabIndex = 3;
            // 
            // otherButton
            // 
            this.otherButton.Location = new System.Drawing.Point(538, 54);
            this.otherButton.Name = "otherButton";
            this.otherButton.Size = new System.Drawing.Size(75, 23);
            this.otherButton.TabIndex = 4;
            this.otherButton.Text = "otherButton";
            this.otherButton.UseVisualStyleBackColor = true;
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(3, 10);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(35, 12);
            this.label1.TabIndex = 3;
            this.label1.Text = "label1";
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(800, 450);
            this.Controls.Add(this.otherButton);
            this.Controls.Add(this.panel1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.panel1.ResumeLayout(false);
            this.panel1.PerformLayout();
            this.ResumeLayout(false);

        }

        #endregion
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.Button otherButton;
        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.Button button2;
        private System.Windows.Forms.Button button3;
        private System.Windows.Forms.Panel panel1;
    }
}

Program.cs

using System;
using System.Windows.Forms;

namespace Questions293390
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(Form1.Instance);
        }
    }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

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

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

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/09/27 15:57

    TN8001様、回答ありがとうございます。
    >void Closed(object sender, FormClosedEventArgs e)のとこですね?
    そうです。
    >それは「ローカル関数」です。メソッド内だけで使える関数なんてのもあるんですね。

    >なぜこのような一見面倒なことをしているかというと、Closed()の中でsubForm・group変数を使いた>かったためです(subFormはsenderを使えばいいですが、groupをほかの方法で渡すのはなかなか難し>いです)
    すいません、私自身のレベルが低く難しさがわからないです。理解できるようにもっと勉強します。

    このたびはありがとうございました。

    キャンセル

  • 2020/09/27 17:30

    凝ったことをやめました^^; これならご理解いただけるでしょう。

    SubFormでTagを使っていないと断定し、Form1で好きに使ってしまう。
    ノイズになっていそうなのでイベント解除を省略(この場合はリークしないはず)

    [【雑記】イベントの購読とその解除 - C# によるプログラミング入門 | ++C++; // 未確認飛行 C](https://ufcpp.net/study/csharp/MiscEventSubscribe.html#must-unsubscribe

    上記のような条件を付けずに汎用的な定型パターンが元のコードというわけです。

    キャンセル

  • 2020/09/27 19:58

    TN8001様、回答の編集ありがとうございます。

    >凝ったことをやめました^^; これならご理解いただけるでしょう。
    >SubFormでTagを使っていないと断定し、Form1で好きに使ってしまう。
    はい、これは分かります。object型のTagプロパティにPanel型のgroup変数をセットすることで、SubForm_FormClosed()メソッドの中でgroup変数を使えるようにしているのですね。
    確かに、ローカル変数を知らないと、is演算子を使ったこのような書き方になりますね。

    先に教えていただいたローカル関数を使ったコードとこのis演算子を使ったコードでは、後者のほうが、
    ・条件文が多い。
    ・行数が多い。
    ・使わなくてもいいプロパティ(Tag)を使っている。
    など、ローカル関数を使ったコードのほうが良いと分かりました。

    丁寧に教えていただきありがとうございました。

    キャンセル

checkベストアンサー

+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/26 17:09 編集

    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メソッドの引数にラムダ式を使ったコード(上記)は見たことがありません。さらに左辺()の中が空白というのも見たことがありません。これはラムダ式やデリゲートを理解すればわかりますか?

    申し訳ありませんが、ご教授お願いいたします。

    キャンセル

  • 2020/09/26 17:41

    > 1

    回答の趣旨は,delegateやラムダを使うことではなく,

    Form1の実装上の都合はForm1が扱えばよい.「ボタンを何個も持っていてそれらを特定のタイミングでDisableにする必要がある」などという具体的な話をForm1の外側に知らせる必要は無い.
    ただし,残念ながら処理タイミングがForm1だけでは把握できない様子なので,ならば,(仕方ないので)「そのタイミングだけは伝達してもらう」ことにする.

    …といった事柄(考え方)です.
    (コード例では IChildForm.ShowModeless()の引数をdelegateとし,そこにForm1側からラムダ式を渡しているが,この実装形態自体は単なる例でしかない.)

    > 2

    それ用のソースファイルを1つ用意してそこに書けばよいでしょう.

    > 3

    これは言語文法的な話なので,勉強するしかないですね.

    キャンセル

  • 2020/09/26 18:04

    fana様、早い回答ありがとうございます。

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

    >それ用のソースファイルを1つ用意してそこに書けばよいでしょう.
    分かりました。

    >これは言語文法的な話なので,勉強するしかないですね.
    はい、勉強します。

    このたびはありがとうございました。

    キャンセル

0

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

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        internal static Form1 form1;

        // コンストラクタ
-       private Form1()
+       public Form1()
        {
            InitializeComponent();
        }

追記

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

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

            Application.Run(new Form1()); 

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

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

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

            foreach (Control c in this.Controls)
            {
                if (c is Button b)
                    b.Enabled = false;
            }

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

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

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

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/09/23 02:09

    gentaro様,回答ありがとうございます。
    >わざわざコンストラクタを呼び出して同じ画面のインスタンスを作成するようなプログラムでなければ、シ>ングルトンにするまでもなく一つしかありません。
    確かにその通りです。すいません,各クラスにメインフォームを参照渡しすると,各クラスにメインフォームを宣言する(Form1 f1;)ので,複数のインスタンスがあると勘違いしていました。

    foreach (Control c in this.Controls)
    {
    if (c is Button b)
    b.Enabled = false;
    }
    はどこに記述すればよいのでしょうか?ご教授お願いいたします。

    キャンセル

  • 2020/09/23 07:09

    > 各クラスにメインフォームを宣言する

    コメントアウトされているコードを見る限り、ただForm1のインスタンスへの参照を保持するだけであれば、インスタンスそのものは1つです。

    > どこに記述すれば

    Commonというクラスを廃止し、そこでやっている処理の代わりにForm1にこういった処理をするメソッドを定義してpublicで定義していれば、Form1への参照を持っている各サブフォームからそのメソッドを呼ぶだけでいいです。

    キャンセル

  • 2020/09/26 15:07

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

    キャンセル

-1

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

例えば、

form.button1.Enabled = flg;

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

また、

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

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

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

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/09/22 19:08

    > Form1は、別スレッドで動いているので、直接、フォーム上のコントロールにアクセスはできません。

    このソースのどこでスレッドが生成されていますか?
    全部UIスレッドで動いてると思いますが。

    キャンセル

  • 2020/09/22 20:03

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

    キャンセル

  • 2020/09/22 21:44

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

    キャンセル

  • 2020/09/23 08:12

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

    キャンセル

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

  • ただいまの回答率 87.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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