回答編集履歴

2

一部訂正

2016/11/08 05:24

投稿

KSwordOfHaste
KSwordOfHaste

スコア18394

test CHANGED
@@ -14,7 +14,7 @@
14
14
 
15
15
 
16
16
 
17
- あくまで実装のイメージを示すだけのものです。本来は登録解除の機能やDisposeしたコントローラーに対して(WeakReferenceを使って)自動的に登録解除したりする仕組みを実装しないと使い物にならないと思います。下記の例では簡単のためTargetEventをstructにしてますがvalur type/classのどちらが適切かは最終実装によってかわるかもしれません。また当然ながらxamlで登録されたハンドラーについては対処のしようがないため、この仕組みを使うコントローラーイベントはxamlで登録しないことが前提になります。
17
+ あくまで実装のイメージを示すだけのものです。本来は登録解除の機能やDisposeしたコントローラーに対して(WeakReferenceを使って)自動的に登録解除したりする仕組みを実装しないと使い物にならないと思います。下記の例では簡単のためTargetEventをstructにしてますがvalur type/classのどちらが適切かは最終実装によってかわるかもしれません。また当然ながらxamlで登録されたハンドラーについては対処のしようがないため、この仕組みを使うコントローラー(ンスタンス)のイベントはxamlで定義しないことが前提になります(xamlで静的に記述したインスタンスのイベントは動的にハンドラーを追加することはないと思えるのでおそらく質問者さんが取り組んでおられるプログラムでは問題にならないと推測します)
18
18
 
19
19
 
20
20
 

1

追記

2016/11/08 05:23

投稿

KSwordOfHaste
KSwordOfHaste

スコア18394

test CHANGED
@@ -3,3 +3,103 @@
3
3
 
4
4
 
5
5
  ハンドラーが登録済みかどうかの判断機能は提供されてないので、必要ならば自分自身で管理するためのコードを書くことになろうかと思います。
6
+
7
+
8
+
9
+ ---
10
+
11
+
12
+
13
+ 多重にハンドラーを登録してしまうことを防ぐ管理コードの一例。
14
+
15
+
16
+
17
+ あくまで実装のイメージを示すだけのものです。本来は登録解除の機能やDisposeしたコントローラーに対して(WeakReferenceを使って)自動的に登録解除したりする仕組みを実装しないと使い物にならないと思います。下記の例では簡単のためTargetEventをstructにしてますがvalur type/classのどちらが適切かは最終実装によってかわるかもしれません。また当然ながらxamlで登録されたハンドラーについては対処のしようがないため、この仕組みを使うコントローラーとイベントはxamlで登録しないことが前提になります。
18
+
19
+
20
+
21
+ 先にも書いたようにeventは+=/-=の左辺にしか使えず(他のメソッドの引数に渡すことさえできない)のでどうしてもこのような迂遠な実装になると思います。(リフレクションとunsafeコードを使うともう少しましにできるのかも知れませんが自分には可能かどうかわかりません)
22
+
23
+
24
+
25
+ ```c#
26
+
27
+ public enum EventCode {
28
+
29
+ CLICKED,
30
+
31
+ ...
32
+
33
+ }
34
+
35
+ public static class HandlerManager {
36
+
37
+ private struct TargetEvent {
38
+
39
+ public Control TargetControl;
40
+
41
+ public EventCode EventCode;
42
+
43
+ }
44
+
45
+
46
+
47
+ private static Dictionary<TargetEvent, EventHandler> registory
48
+
49
+ = new Dictionary<TargetEvent, EventHandler>();
50
+
51
+
52
+
53
+ public static bool RegisterIfAny(Control c, EventCode ec, EventHandler handler) {
54
+
55
+ TargetEvent te = new TargetEvent { TargetControl = c, EventCode = ec };
56
+
57
+ EventHandler h;
58
+
59
+ if (registory.TryGetValue(te, out h)) {
60
+
61
+ return false;
62
+
63
+ } else {
64
+
65
+ registory.Add(te, handler);
66
+
67
+ return true;
68
+
69
+ }
70
+
71
+ }
72
+
73
+ }
74
+
75
+
76
+
77
+ // 上記を使ったハンドラー登録の例
78
+
79
+
80
+
81
+ public partial class Form1 : Form {
82
+
83
+ public Form1() {
84
+
85
+ InitializeComponent();
86
+
87
+ // 以下のように2回登録しても最初しか登録されない
88
+
89
+ if (HandlerManager.RegisterIfAny(button1, EventCode.CLICKED, button1_Click))
90
+
91
+ button1.Click += button1_Click;
92
+
93
+ if (HandlerManager.RegisterIfAny(button1, EventCode.CLICKED, button1_Click))
94
+
95
+ button1.Click += button1_Click;
96
+
97
+ }
98
+
99
+ }
100
+
101
+ ...
102
+
103
+ }
104
+
105
+ ```