回答編集履歴

1

見直しキャンペーン中

2023/07/22 10:19

投稿

TN8001
TN8001

スコア9862

test CHANGED
@@ -1,523 +1,262 @@
1
1
  YAmaGNZさん 2020/08/05 23:24 のコメントのざっくり実装です。
2
2
 
3
-
4
-
5
3
  同様のものを作るのは大変なので、以下のように置き換えさせていただきます。
6
-
7
4
  ユーザーコントロール → Form1(Form)
8
-
9
5
  SplitContainerを拡張したコンポーネント → ParentPanel(FlowLayoutPanel)
10
-
11
6
  SplitterPanelを拡張したコンポーネント → ChildPanel(Panel)
12
7
 
13
-
14
-
15
8
  ChildPanelの追加・削除時にイベント登録・解除して、新しく作った専用のイベントにまわすだけです。
16
-
17
9
  本題に関係ないコードのほうが多いですが、ポイントはコメントが入ってる部分だけです。
18
10
 
19
-
20
-
21
- ```C#
11
+ ```cs
22
-
23
12
  using System;
24
-
25
13
  using System.Collections.Generic;
26
-
27
14
  using System.Diagnostics;
28
-
29
15
  using System.Drawing;
30
-
31
16
  using System.Linq;
32
-
33
17
  using System.Windows.Forms;
34
18
 
35
-
36
-
37
19
  namespace Questions282825
38
-
39
20
  {
40
-
41
21
  public partial class Form1 : Form
42
-
43
22
  {
44
-
45
23
  private ParentPanel parentPanel;
46
-
47
24
  private ListBox listBox;
48
25
 
49
-
50
-
51
26
  public Form1()
52
-
53
- {
27
+ {
54
-
55
28
  InitializeComponent();
56
29
 
57
-
58
-
59
30
  parentPanel = new ParentPanel() { Dock = DockStyle.Fill, };
60
31
 
61
-
62
-
63
32
  // 子供クリックイベントの登録
64
-
65
33
  parentPanel.ChildClick += ParentPanel_ChildClick;
66
-
67
34
  Controls.Add(parentPanel);
68
35
 
69
-
70
-
71
36
  var addButton = new Button { Dock = DockStyle.Bottom, Text = "add", };
72
-
73
37
  addButton.Click += AddButton_Click;
74
38
 
75
-
76
-
77
39
  var clearButton = new Button { Dock = DockStyle.Top, Text = "clear", };
78
-
79
40
  clearButton.Click += ClearButton_Click;
80
41
 
81
-
82
-
83
42
  var tableLayoutPanel = new TableLayoutPanel { Dock = DockStyle.Left, Width = 80, };
84
-
85
43
  tableLayoutPanel.Controls.Add(addButton, 0, 0);
86
-
87
44
  tableLayoutPanel.Controls.Add(clearButton, 0, 1);
88
-
89
45
  tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
90
-
91
46
  tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
92
-
93
47
  Controls.Add(tableLayoutPanel);
94
48
 
95
-
96
-
97
49
  listBox = new ListBox { Dock = DockStyle.Left, SelectionMode = SelectionMode.MultiSimple, };
98
-
99
50
  listBox.DataSource = new Color[] { Color.Red, Color.Green, Color.Blue, };
100
-
101
51
  Controls.Add(listBox);
102
-
103
- }
52
+ }
104
-
105
-
106
53
 
107
54
  private void ParentPanel_ChildClick(object sender, EventArgs e)
108
-
109
- {
55
+ {
110
-
111
56
  if(sender is Control control)
112
-
113
- {
57
+ {
114
-
115
58
  Debug.WriteLine($"{control.Name} {control.BackColor}");
116
-
117
- }
59
+ }
118
-
119
- }
60
+ }
120
-
121
-
122
61
 
123
62
  private void AddButton_Click(object sender, EventArgs e)
124
-
125
- {
63
+ {
126
-
127
64
  var colors = listBox.SelectedItems.Cast<Color>();
128
-
129
65
  parentPanel.AddRange(colors);
130
-
131
- }
66
+ }
132
-
133
-
134
67
 
135
68
  private void ClearButton_Click(object sender, EventArgs e)
136
-
137
- {
69
+ {
138
-
139
70
  parentPanel.Clear();
140
-
141
- }
71
+ }
142
-
143
-
144
-
145
72
 
146
73
 
147
74
  class ParentPanel : FlowLayoutPanel
148
-
149
- {
75
+ {
150
-
151
76
  // 新しく作った子供クリックイベント
152
-
153
77
  public event EventHandler ChildClick;
154
78
 
155
-
156
-
157
79
  public void AddRange(IEnumerable<Color> colors)
158
-
159
- {
80
+ {
160
-
161
81
  foreach(var color in colors)
162
-
163
- {
82
+ {
164
-
165
83
  var child = new ChildPanel(color);
166
84
 
167
-
168
-
169
85
  // 追加時にイベント登録
170
-
171
86
  child.Click += Child_Click;
172
-
173
87
  Controls.Add(child);
174
-
175
- }
88
+ }
176
-
177
- }
89
+ }
178
-
179
-
180
90
 
181
91
  public void Clear()
182
-
183
- {
92
+ {
184
-
185
93
  foreach(var child in Controls.Cast<Control>().ToArray())
186
-
187
- {
94
+ {
188
-
189
95
  // 削除時にイベント解除
190
-
191
96
  child.Click -= Child_Click;
192
-
193
97
  Controls.Remove(child);
194
-
195
98
  child.Dispose();
196
-
197
- }
99
+ }
198
-
199
- }
100
+ }
200
-
201
-
202
101
 
203
102
  private void Child_Click(object sender, EventArgs e)
204
-
205
- {
103
+ {
206
-
207
104
  // 子供クリックイベントを発砲(sender e そのまま渡しは雑い^^;
208
-
209
105
  ChildClick?.Invoke(sender, e);
210
-
211
- }
106
+ }
212
-
213
- }
107
+ }
214
-
215
-
216
108
 
217
109
  class ChildPanel : Panel
218
-
219
- {
110
+ {
220
-
221
111
  private static int i;
222
112
 
223
-
224
-
225
113
  public ChildPanel(Color color)
226
-
227
- {
114
+ {
228
-
229
115
  Name = $"Panel{++i}";
230
-
231
116
  Width = 100;
232
-
233
117
  Height = 100;
234
-
235
118
  BackColor = color;
236
-
237
- }
119
+ }
238
-
239
- }
120
+ }
240
-
241
121
  }
242
-
243
122
  }
244
-
245
123
  ```
246
124
 
247
-
248
-
249
125
  > そのたびにSplitterPanelに対してイベントを付与する必要
250
126
 
251
-
252
-
253
127
  もしかして「やれるのはわかっているが、いちいち登録解除がめんどくさい」って意味でしょうか?
254
128
 
255
-
256
-
257
129
  こんなソリューションがありました(この要件だとオーバーすぎる気がしますが)
258
-
259
130
  [Broadcasting Events through a Control Hierarchy - CodeProject](https://www.codeproject.com/Articles/13216/Broadcasting-Events-through-a-Control-Hierarchy)
260
-
261
131
  たしか無料登録しないとダウンロードできなかったと思うので、面倒な場合こちら(おそらく↑そのまま)
262
-
263
132
  [POSTSTAR/EventBroadcastProvider.cs at master · ohintaek/POSTSTAR](https://github.com/ohintaek/POSTSTAR/blob/master/PostStar.Basic/Common/EventBroadcastProvider.cs)
264
133
 
265
-
266
-
267
134
  最初読み違えて`SplitContainer`を多段に入れ子すると思っていたので、そんな作りになってしまっています^^;
268
135
 
269
-
270
-
271
- ```C#
136
+ ```cs
272
-
273
137
  using System;
274
-
275
138
  using System.Collections.Generic;
276
-
277
139
  using System.Diagnostics;
278
-
279
140
  using System.Drawing;
280
-
281
141
  using System.Linq;
282
-
283
142
  using System.Windows.Forms;
284
143
 
285
-
286
-
287
144
  namespace Questions282825
288
-
289
145
  {
290
-
291
146
  public partial class Form1 : Form
292
-
293
147
  {
294
-
295
148
  public Form1()
296
-
297
- {
149
+ {
298
-
299
150
  InitializeComponent();
300
151
 
301
-
302
-
303
152
  var splitContainer = new MySplitContainer();
304
-
305
153
  Controls.Add(splitContainer);
306
154
 
307
-
308
-
309
155
  // どちらにしろこれは必須
310
-
311
156
  var broadcastProvider = EventBroadcastProvider.CreateProvider(splitContainer, "Click");
312
157
 
313
-
314
-
315
158
  // 単にクリックが拾えればいい場合
316
-
317
159
  splitContainer.Click += SplitContainer_Click;
318
160
 
319
-
320
-
321
161
  // クリックされたコントロールやツリーも欲しい場合
322
-
323
162
  broadcastProvider.Relayed += BroadcastProvider_Relayed;
324
-
325
- }
163
+ }
326
-
327
-
328
164
 
329
165
  private void SplitContainer_Click(object sender, EventArgs e)
330
-
331
- {
166
+ {
332
-
333
167
  Debug.WriteLine("Click");
334
-
335
- }
168
+ }
336
-
337
-
338
169
 
339
170
  private void BroadcastProvider_Relayed(object sender, RelayedEventArgs e)
340
-
341
- {
171
+ {
342
-
343
172
  if(e.RelayChain[0] is Control control)
344
-
345
- {
173
+ {
346
-
347
174
  Debug.WriteLine($"{control.Name} {control.BackColor}");
348
-
349
- }
175
+ }
350
-
351
- }
176
+ }
352
-
353
-
354
-
355
177
 
356
178
 
357
179
  // 本題には関係ないが検証用に雑に作成
358
-
359
180
  class MySplitContainer : SplitContainer
360
-
361
- {
181
+ {
362
-
363
182
  private static List<KnownColor> colors;
364
-
365
183
  private static Random random = new Random();
366
-
367
184
  private static int i;
368
185
 
369
-
370
-
371
186
  private static ContextMenuStrip contextMenuStrip;
372
-
373
187
  private static ToolStripMenuItem addToolStripMenuItem;
374
-
375
188
  private static ToolStripMenuItem delToolStripMenuItem;
376
189
 
377
-
378
-
379
190
  static MySplitContainer()
380
-
381
- {
191
+ {
382
-
383
192
  colors = Enum.GetValues(typeof(KnownColor)).Cast<KnownColor>().ToList();
384
193
 
385
-
386
-
387
194
  addToolStripMenuItem = new ToolStripMenuItem { Text = "追加", };
388
-
389
195
  addToolStripMenuItem.Click += AddToolStripMenuItem_Click;
390
196
 
391
-
392
-
393
197
  delToolStripMenuItem = new ToolStripMenuItem { Text = "削除", };
394
-
395
198
  delToolStripMenuItem.Click += DelToolStripMenuItem_Click;
396
199
 
397
-
398
-
399
200
  contextMenuStrip = new ContextMenuStrip();
400
-
401
201
  contextMenuStrip.Items.Add(addToolStripMenuItem);
402
-
403
202
  contextMenuStrip.Items.Add(delToolStripMenuItem);
404
-
405
- }
203
+ }
406
-
407
-
408
204
 
409
205
  public MySplitContainer()
410
-
411
- {
206
+ {
412
-
413
207
  BorderStyle = BorderStyle.Fixed3D;
414
-
415
208
  Dock = DockStyle.Fill;
416
209
 
417
-
418
-
419
210
  Panel1.Name = $"Panel{++i}";
420
-
421
211
  Panel2.Name = $"Panel{++i}";
422
212
 
423
-
424
-
425
213
  Panel1.ContextMenuStrip = contextMenuStrip;
426
-
427
214
  Panel2.ContextMenuStrip = contextMenuStrip;
428
215
 
429
-
430
-
431
216
  Panel1.BackColor = Color.FromKnownColor(colors.Skip(random.Next(0, colors.Count)).First());
432
-
433
217
  Panel2.BackColor = Color.FromKnownColor(colors.Skip(random.Next(0, colors.Count)).First());
434
-
435
- }
218
+ }
436
-
437
-
438
219
 
439
220
  private static void AddToolStripMenuItem_Click(object sender, EventArgs e)
440
-
441
- {
221
+ {
442
-
443
222
  if(sender is ToolStripItem item)
444
-
445
- {
223
+ {
446
-
447
224
  if(item.Owner is ContextMenuStrip menuStrip)
448
-
449
225
  {
450
-
451
226
  if(menuStrip.SourceControl is SplitterPanel panel)
452
-
453
227
  {
454
-
455
228
  var o = (int)Orientation.Vertical;
456
-
457
229
  if(panel.Parent is SplitContainer container)
458
-
459
230
  {
460
-
461
231
  o = (int)container.Orientation;
462
-
463
232
  o ^= 1;
464
-
465
233
  }
466
234
 
467
-
468
-
469
235
  var sc = new MySplitContainer { Orientation = (Orientation)o };
470
-
471
236
  panel.Controls.Add(sc);
472
-
473
237
  }
474
-
475
238
  }
476
-
477
- }
239
+ }
478
-
479
- }
240
+ }
480
-
481
-
482
241
 
483
242
  private static void DelToolStripMenuItem_Click(object sender, EventArgs e)
484
-
485
- {
243
+ {
486
-
487
244
  if(sender is ToolStripItem item)
488
-
489
- {
245
+ {
490
-
491
246
  if(item.Owner is ContextMenuStrip menuStrip)
492
-
493
247
  {
494
-
495
248
  if(menuStrip.SourceControl is SplitterPanel panel)
496
-
497
249
  {
498
-
499
250
  if(panel.Parent is SplitContainer container)
500
-
501
251
  {
502
-
503
252
  container.Parent.Controls.Remove(container);
504
-
505
253
  container.Dispose();
506
-
507
254
  }
508
-
509
255
  }
510
-
511
256
  }
512
-
513
- }
257
+ }
514
-
515
- }
258
+ }
516
-
517
- }
259
+ }
518
-
519
260
  }
520
-
521
261
  }
522
-
523
262
  ```