🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

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

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

Q&A

解決済

1回答

1165閲覧

大量のメンバ変数の数値を変更可能なNumericUpDownを動的に生成したいがうまく動作しない

gamu

総合スコア31

C#

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

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

0グッド

0クリップ

投稿2019/10/15 02:35

こんにちは。
以下のように、大量の設定項目があり、それをユーザーが微調整できるようにしたいと思っています。
ちなみにその設定の保存、読み込みはManySettingインスタンスのシリアライズ/デシリアライズで別途行おうと考えています。

C#

1 class ManySetting 2 { 3 float CarWidth; 4 float CarHeight; 5 float CarWeight; 6 float CarLength; 7 float CarPrice; 8 float CarHoge; 9 //.....といったような変数が100個あります 10 } 11

これらに対してフォームデザイナーで手作業でNumericUpDownを配置するのは手間がかかるので、動的にコントロールのリストを生成し、適当なPanel(panelTekitou)のControlsに追加しようと思いました。

C#

1void SettingInitialize(){ 2 3 List<Control> controls = new List<Control>(); 4 5 AddNumericUpDownToControlList( 6 controls, 7 "車の幅", 8 (decimal)2.0,(decimal)0.001,(decimal)0.001,3, 9 ref manySettingInstance.CarWidth); 10 AddNumericUpDownToControlList( 11 controls, 12 "車の高さ", 13 (decimal)2.0,(decimal)0.001,(decimal)0.001,3, 14 ref manySettingInstance.CarWidth); 15 //などなど100個続く 16 17 panelTekitou.Controls.AddRange(controls.ToArray()); 18 19 } 20 21 22 int settingCount = 0; 23 24 internal void AddNumericUpDownToControlList(List<Control> controls, string description, decimal max, decimal min, decimal increment, int decimalPlaces, 25 ref float targetObj) 26 { 27 28 NumericUpDown nu = new NumericUpDown(); 29 nu.Width = 60; 30 nu.Increment = increment; 31 nu.Maximum = max; 32 nu.Minimum = min; 33 nu.DecimalPlaces = decimalPlaces; 34 nu.Location = new Point(0, settingCount * 20); 35 nu.ValueChanged += new EventHandler(numericUpDownAnySetting_ValueChanged); 36 nu.Tag = targetObj; 37 if (targetObj is float fl) 38 { 39 decimal de = (decimal)fl; 40 if (de >= min && de <= max) 41 { 42 nu.Value = (decimal)fl; 43 } 44 } 45 46 47 Label lblDesc = new Label(); 48 lblDesc.TextAlign = ContentAlignment.MiddleLeft; 49 lblDesc.AutoSize = true; 50 lblDesc.Text = (settingCount + 1).ToString() + " " + description; 51 lblDesc.Location = new Point(80, settingCount * 20); 52 lblDesc.BackColor = Color.FromArgb(240, 240, 240); 53 54 controls.Add(nu); 55 controls.Add(lblDesc); 56 57 settingCount++; 58 } 59 60 61 /// <summary> 62 /// 設定の変更のイベント 63 /// </summary> 64 /// <param name="sender"></param> 65 /// <param name="e"></param> 66 private void numericUpDownAnySetting_ValueChanged(object sender, EventArgs e) 67 { 68 if (sender is NumericUpDown nu) 69 { 70 nu.Refresh(); //再描画 71 72 if (nu.Tag is float) 73 { 74 nu.Tag = (float)nu.Value; 75 } 76 } 77 } 78 79

その後ですが、
NumericUpDownのTagに割り当てた変数が値渡しになってしまうようで、希望の設定インスタンスに反映することができません。
refキーワードを随所にこれでもかと散りばめているのは、参照して欲しくてつけた為です。
稚拙な内容かもしれませんが紐付けするためのアドバイスを頂けると幸いです。

よろしくおねがいします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

Tag プロパティに保存するのは、値ではなく、値をリフレクションで読み出すための FieldInfo クラスオブジェクトを格納すると良いと思います。

AddNumericUpDownToControlList の最後の引数をフィールド名にし、値セットの部分を以下のようにします。

C#

1using System.Reflection; 2 3internal void AddNumericUpDownToControlList( 4 List<Control> controls, 5 string description, 6 decimal max, 7 decimal min, 8 decimal increment, 9 int decimalPlaces, 10 string fieldName 11 ) { 12 13 // (略) 14 15 // FieldInfo を取得 16 const BindingFlags flags = BindingFlags.Instance | 17 BindingFlags.Public | 18 BindingFlags.NonPublic; 19 FieldInfo fieldInfo = typeof(ManySetting).GetField(fieldName, flags); 20 21 // Tag には fieldInfo を渡す 22 nu.Tag = fieldInfo; 23 24 // 値のセット 25 float fl = (float)fieldInfo.GetValue(manySettingInstance); 26 decimal de = (decimal)fl; 27 if (de >= min && de <= max) { 28 nu.Value = (decimal)fl; 29 } 30 31 // (略) 32 33}

ValueChanged イベントでは Tag から FieldInfo を取得して SetValue します。

C#

1private void numericUpDownAnySetting_ValueChanged(object sender, EventArgs e) { 2 if (sender is NumericUpDown nu) { 3 if (nu.Tag is FieldInfo fieldInfo) { 4 fieldInfo.SetValue(manySettingInstance, (float)nu.Value); 5 } 6 } 7}

呼び出すときは

C#

1 AddNumericUpDownToControlList( 2 controls, "車の幅", 2.0m, 0.001m, 0.001m, 3, "CarWidth");

投稿2019/10/15 06:16

KOZ6.0

総合スコア2707

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gamu

2019/10/15 06:28

こういった事ができるのですね。非常に参考になりました。 解決でき、嬉しいです。 お付き合いいただき、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問