質問編集履歴

5

原因の掲示

2018/09/28 12:52

投稿

nekome4
nekome4

スコア24

test CHANGED
File without changes
test CHANGED
@@ -120,11 +120,13 @@
120
120
 
121
121
 
122
122
 
123
- 3.デフォルト値をnew Hoge(0,0)としてしまうとOnApplyTemplateでのFoo初期化時に同値?とみなされてしまい変更通知がいかなかったためnew Hoge(1,1)としましたがこの方法しかないでしょうか?
123
+ ~~3.デフォルト値をnew Hoge(0,0)としてしまうとOnApplyTemplateでのFoo初期化時に同値?とみなされてしまい変更通知がいかなかったためnew Hoge(1,1)としましたがこの方法しかないでしょうか?~~
124
+
124
-
125
+ 質問5で解決したかもしれません。
125
-
126
-
126
+
127
+
128
+
127
- 4.今回は必要ありませんが、オブジェクトのプロパティごとに変更の通知をしたい場合はどのようにすればよいのでしょう?
129
+ ~~4.今回は必要ありませんが、オブジェクトのプロパティごとに変更の通知をしたい場合はどのようにすればよいのでしょう?~~
128
130
 
129
131
 
130
132
 
@@ -134,7 +136,7 @@
134
136
 
135
137
 
136
138
 
137
- #追加質問
139
+ #追加質問(解決)
138
140
 
139
141
  5.以下のように"B"のFooのバインディングモードをOneWayにして"A"のFooの内容を変更しても"B"に反映されません。TwoWayにすると反映されます。何故でしょうか?
140
142
 
@@ -201,3 +203,51 @@
201
203
  そこでFooの構造体をPaddingなどで使われているThicknessに置き換えるとやはり同様の問題が発生します。
202
204
 
203
205
  以上の事からDependencyPropertyの作り方に何か問題があるのではないかと推測しています。
206
+
207
+
208
+
209
+ ---
210
+
211
+ 本現象の原因がわかりましたのでサンプルなどを交えて記載しておきます。
212
+
213
+ 原因はOnApplyTemplate()でのHogeのインスタンス生成、「構造体の依存プロパティに対しての値代入」でした。
214
+
215
+ なので、以下のようにして構造体の依存プロパティに対して値を代入しないようにします。
216
+
217
+ (質問3での変更通知のために代入していましたが、無くしてしまうと困るので代わりにメタデータからコールバック関数を強制的に呼ぶようにしました。)
218
+
219
+ ```C#
220
+
221
+ public override void OnApplyTemplate()
222
+
223
+ {
224
+
225
+ base.OnApplyTemplate();
226
+
227
+
228
+
229
+ // Foo = new Hoge(0, 0);
230
+
231
+ FooProperty.GetMetadata(FooProperty.OwnerType).PropertyChangedCallback(
232
+
233
+ this, new DependencyPropertyChangedEventArgs(FooProperty, Foo, Foo));
234
+
235
+ }
236
+
237
+ ```
238
+
239
+ この状態で、"A"のコントロール領域内でマウスダウンをすると"B"に"A"の内容が反映されることが確認できます。
240
+
241
+ この時、"A"のコントロールのFooやPaddingプロパティに対して値を代入していますが、問題が発生するのはターゲット(この場合"B")のプロパティに対して値を代入する時だけのようです。
242
+
243
+ なので、"B"のコントロール領域内でマウスダウンをするとこのコントロールのFooとPaddingに値が代入されてしまうので以降"A"でマウスダウンをしても反映されなくなってしまいます。これはバグ?仕様?わかりません・・・。
244
+
245
+
246
+
247
+ しかしながらPaddingと同じ動作になっていますのでこれ以上できる事は無いと思いました 。
248
+
249
+ できることとしては常にTwoWayにするか、OneWayToSourceを使うか、値の更新をしないことが分かっている時のみOneWayを使う・・・ぐらいです。
250
+
251
+
252
+
253
+ ※HogeにTypeConverterを使ってみましたがこちらは問題は発生しませんでした。

4

コードの追加

2018/09/28 12:52

投稿

nekome4
nekome4

スコア24

test CHANGED
File without changes
test CHANGED
@@ -150,6 +150,50 @@
150
150
 
151
151
  ```
152
152
 
153
+ ```C#
154
+
155
+ protected override void OnMouseDown(MouseButtonEventArgs e)
156
+
157
+ {
158
+
159
+ base.OnMouseDown(e);
160
+
161
+
162
+
163
+ // NG
164
+
165
+ Hoge foo = Foo;
166
+
167
+ foo.X += 1;
168
+
169
+ Foo = foo;
170
+
171
+
172
+
173
+ // OK
174
+
175
+ Thickness p = Padding;
176
+
177
+ p.Left += 1;
178
+
179
+ Padding = p;
180
+
181
+ /*
182
+
183
+ // HogeをThicknessにした場合もNG
184
+
185
+ Thickness foo = Foo;
186
+
187
+ foo.Left += 1;
188
+
189
+ Foo = foo;
190
+
191
+ */
192
+
193
+ }
194
+
195
+ ```
196
+
153
197
  Foo(Hoge構造体)をPadding(Thickness構造体)に置き換えた場合はうまくバインディングが機能してくれます。
154
198
 
155
199
 

3

コードの修正

2018/09/28 00:23

投稿

nekome4
nekome4

スコア24

test CHANGED
File without changes
test CHANGED
@@ -112,9 +112,17 @@
112
112
 
113
113
  1.目的を実現するにあたってこの実装方法でよいのでしょうか?
114
114
 
115
+
116
+
115
117
  2.依存プロパティを構造体にしているため値変更時に一度コピーしてから変更、そして元に戻すという事をしています。ちょっと不細工なのでもっとスマートに記述する方法はありますか?
116
118
 
119
+ (編集用のprivateな変数を作りデータが出来上がった(更新時)ら、「Foo=_foo」とするのがいいかと思いました。)
120
+
121
+
122
+
117
123
  3.デフォルト値をnew Hoge(0,0)としてしまうとOnApplyTemplateでのFoo初期化時に同値?とみなされてしまい変更通知がいかなかったためnew Hoge(1,1)としましたがこの方法しかないでしょうか?
124
+
125
+
118
126
 
119
127
  4.今回は必要ありませんが、オブジェクトのプロパティごとに変更の通知をしたい場合はどのようにすればよいのでしょう?
120
128
 
@@ -141,3 +149,11 @@
141
149
  <Controls1:CustomControl1 x:Name="B" Foo="{Binding ElementName=A, Path=Foo, Mode=OneWay}" Width="200" Height="50" Grid.Row="1"/>
142
150
 
143
151
  ```
152
+
153
+ Foo(Hoge構造体)をPadding(Thickness構造体)に置き換えた場合はうまくバインディングが機能してくれます。
154
+
155
+
156
+
157
+ そこでFooの構造体をPaddingなどで使われているThicknessに置き換えるとやはり同様の問題が発生します。
158
+
159
+ 以上の事からDependencyPropertyの作り方に何か問題があるのではないかと推測しています。

2

追加の質問

2018/09/28 00:06

投稿

nekome4
nekome4

スコア24

test CHANGED
File without changes
test CHANGED
@@ -120,4 +120,24 @@
120
120
 
121
121
 
122
122
 
123
+
124
+
123
125
  当方WPF(C#)初心者のためまだよくわかっていなことがたくさんありますが、どうかご教示よろしくお願いいたします。
126
+
127
+
128
+
129
+ #追加質問
130
+
131
+ 5.以下のように"B"のFooのバインディングモードをOneWayにして"A"のFooの内容を変更しても"B"に反映されません。TwoWayにすると反映されます。何故でしょうか?
132
+
133
+
134
+
135
+ ```XAML
136
+
137
+ <Controls1:CustomControl1 x:Name="A" Width="200" Height="50" Grid.Row="0"/>
138
+
139
+
140
+
141
+ <Controls1:CustomControl1 x:Name="B" Foo="{Binding ElementName=A, Path=Foo, Mode=OneWay}" Width="200" Height="50" Grid.Row="1"/>
142
+
143
+ ```

1

コードの修正

2018/09/27 12:15

投稿

nekome4
nekome4

スコア24

test CHANGED
File without changes
test CHANGED
@@ -30,7 +30,7 @@
30
30
 
31
31
  {
32
32
 
33
- private static readonly DependencyProperty FooProperty = DependencyProperty.Register(
33
+ public static readonly DependencyProperty FooProperty = DependencyProperty.Register(
34
34
 
35
35
  "Foo", typeof(Hoge),
36
36