質問するログイン新規登録

質問編集履歴

5

原因の掲示

2018/09/28 12:52

投稿

nekome4
nekome4

スコア24

title CHANGED
File without changes
body CHANGED
@@ -59,14 +59,15 @@
59
59
  2.依存プロパティを構造体にしているため値変更時に一度コピーしてから変更、そして元に戻すという事をしています。ちょっと不細工なのでもっとスマートに記述する方法はありますか?
60
60
  (編集用のprivateな変数を作りデータが出来上がった(更新時)ら、「Foo=_foo」とするのがいいかと思いました。)
61
61
 
62
- 3.デフォルト値をnew Hoge(0,0)としてしまうとOnApplyTemplateでのFoo初期化時に同値?とみなされてしまい変更通知がいかなかったためnew Hoge(1,1)としましたがこの方法しかないでしょうか?
62
+ ~~3.デフォルト値をnew Hoge(0,0)としてしまうとOnApplyTemplateでのFoo初期化時に同値?とみなされてしまい変更通知がいかなかったためnew Hoge(1,1)としましたがこの方法しかないでしょうか?~~
63
+ 質問5で解決したかもしれません。
63
64
 
64
- 4.今回は必要ありませんが、オブジェクトのプロパティごとに変更の通知をしたい場合はどのようにすればよいのでしょう?
65
+ ~~4.今回は必要ありませんが、オブジェクトのプロパティごとに変更の通知をしたい場合はどのようにすればよいのでしょう?~~
65
66
 
66
67
 
67
68
  当方WPF(C#)初心者のためまだよくわかっていなことがたくさんありますが、どうかご教示よろしくお願いいたします。
68
69
 
69
- #追加質問
70
+ #追加質問(解決)
70
71
  5.以下のように"B"のFooのバインディングモードをOneWayにして"A"のFooの内容を変更しても"B"に反映されません。TwoWayにすると反映されます。何故でしょうか?
71
72
 
72
73
  ```XAML
@@ -99,4 +100,28 @@
99
100
  Foo(Hoge構造体)をPadding(Thickness構造体)に置き換えた場合はうまくバインディングが機能してくれます。
100
101
 
101
102
  そこでFooの構造体をPaddingなどで使われているThicknessに置き換えるとやはり同様の問題が発生します。
102
- 以上の事からDependencyPropertyの作り方に何か問題があるのではないかと推測しています。
103
+ 以上の事からDependencyPropertyの作り方に何か問題があるのではないかと推測しています。
104
+
105
+ ---
106
+ 本現象の原因がわかりましたのでサンプルなどを交えて記載しておきます。
107
+ 原因はOnApplyTemplate()でのHogeのインスタンス生成、「構造体の依存プロパティに対しての値代入」でした。
108
+ なので、以下のようにして構造体の依存プロパティに対して値を代入しないようにします。
109
+ (質問3での変更通知のために代入していましたが、無くしてしまうと困るので代わりにメタデータからコールバック関数を強制的に呼ぶようにしました。)
110
+ ```C#
111
+ public override void OnApplyTemplate()
112
+ {
113
+ base.OnApplyTemplate();
114
+
115
+ // Foo = new Hoge(0, 0);
116
+ FooProperty.GetMetadata(FooProperty.OwnerType).PropertyChangedCallback(
117
+ this, new DependencyPropertyChangedEventArgs(FooProperty, Foo, Foo));
118
+ }
119
+ ```
120
+ この状態で、"A"のコントロール領域内でマウスダウンをすると"B"に"A"の内容が反映されることが確認できます。
121
+ この時、"A"のコントロールのFooやPaddingプロパティに対して値を代入していますが、問題が発生するのはターゲット(この場合"B")のプロパティに対して値を代入する時だけのようです。
122
+ なので、"B"のコントロール領域内でマウスダウンをするとこのコントロールのFooとPaddingに値が代入されてしまうので以降"A"でマウスダウンをしても反映されなくなってしまいます。これはバグ?仕様?わかりません・・・。
123
+
124
+ しかしながらPaddingと同じ動作になっていますのでこれ以上できる事は無いと思いました 。
125
+ できることとしては常にTwoWayにするか、OneWayToSourceを使うか、値の更新をしないことが分かっている時のみOneWayを使う・・・ぐらいです。
126
+
127
+ ※HogeにTypeConverterを使ってみましたがこちらは問題は発生しませんでした。

4

コードの追加

2018/09/28 12:52

投稿

nekome4
nekome4

スコア24

title CHANGED
File without changes
body CHANGED
@@ -74,6 +74,28 @@
74
74
 
75
75
  <Controls1:CustomControl1 x:Name="B" Foo="{Binding ElementName=A, Path=Foo, Mode=OneWay}" Width="200" Height="50" Grid.Row="1"/>
76
76
  ```
77
+ ```C#
78
+ protected override void OnMouseDown(MouseButtonEventArgs e)
79
+ {
80
+ base.OnMouseDown(e);
81
+
82
+ // NG
83
+ Hoge foo = Foo;
84
+ foo.X += 1;
85
+ Foo = foo;
86
+
87
+ // OK
88
+ Thickness p = Padding;
89
+ p.Left += 1;
90
+ Padding = p;
91
+ /*
92
+ // HogeをThicknessにした場合もNG
93
+ Thickness foo = Foo;
94
+ foo.Left += 1;
95
+ Foo = foo;
96
+ */
97
+ }
98
+ ```
77
99
  Foo(Hoge構造体)をPadding(Thickness構造体)に置き換えた場合はうまくバインディングが機能してくれます。
78
100
 
79
101
  そこでFooの構造体をPaddingなどで使われているThicknessに置き換えるとやはり同様の問題が発生します。

3

コードの修正

2018/09/28 00:23

投稿

nekome4
nekome4

スコア24

title CHANGED
File without changes
body CHANGED
@@ -55,8 +55,12 @@
55
55
  ここでいくつか質問があります。
56
56
 
57
57
  1.目的を実現するにあたってこの実装方法でよいのでしょうか?
58
+
58
59
  2.依存プロパティを構造体にしているため値変更時に一度コピーしてから変更、そして元に戻すという事をしています。ちょっと不細工なのでもっとスマートに記述する方法はありますか?
60
+ (編集用のprivateな変数を作りデータが出来上がった(更新時)ら、「Foo=_foo」とするのがいいかと思いました。)
61
+
59
62
  3.デフォルト値をnew Hoge(0,0)としてしまうとOnApplyTemplateでのFoo初期化時に同値?とみなされてしまい変更通知がいかなかったためnew Hoge(1,1)としましたがこの方法しかないでしょうか?
63
+
60
64
  4.今回は必要ありませんが、オブジェクトのプロパティごとに変更の通知をしたい場合はどのようにすればよいのでしょう?
61
65
 
62
66
 
@@ -69,4 +73,8 @@
69
73
  <Controls1:CustomControl1 x:Name="A" Width="200" Height="50" Grid.Row="0"/>
70
74
 
71
75
  <Controls1:CustomControl1 x:Name="B" Foo="{Binding ElementName=A, Path=Foo, Mode=OneWay}" Width="200" Height="50" Grid.Row="1"/>
72
- ```
76
+ ```
77
+ Foo(Hoge構造体)をPadding(Thickness構造体)に置き換えた場合はうまくバインディングが機能してくれます。
78
+
79
+ そこでFooの構造体をPaddingなどで使われているThicknessに置き換えるとやはり同様の問題が発生します。
80
+ 以上の事からDependencyPropertyの作り方に何か問題があるのではないかと推測しています。

2

追加の質問

2018/09/28 00:06

投稿

nekome4
nekome4

スコア24

title CHANGED
File without changes
body CHANGED
@@ -59,4 +59,14 @@
59
59
  3.デフォルト値をnew Hoge(0,0)としてしまうとOnApplyTemplateでのFoo初期化時に同値?とみなされてしまい変更通知がいかなかったためnew Hoge(1,1)としましたがこの方法しかないでしょうか?
60
60
  4.今回は必要ありませんが、オブジェクトのプロパティごとに変更の通知をしたい場合はどのようにすればよいのでしょう?
61
61
 
62
+
62
- 当方WPF(C#)初心者のためまだよくわかっていなことがたくさんありますが、どうかご教示よろしくお願いいたします。
63
+ 当方WPF(C#)初心者のためまだよくわかっていなことがたくさんありますが、どうかご教示よろしくお願いいたします。
64
+
65
+ #追加質問
66
+ 5.以下のように"B"のFooのバインディングモードをOneWayにして"A"のFooの内容を変更しても"B"に反映されません。TwoWayにすると反映されます。何故でしょうか?
67
+
68
+ ```XAML
69
+ <Controls1:CustomControl1 x:Name="A" Width="200" Height="50" Grid.Row="0"/>
70
+
71
+ <Controls1:CustomControl1 x:Name="B" Foo="{Binding ElementName=A, Path=Foo, Mode=OneWay}" Width="200" Height="50" Grid.Row="1"/>
72
+ ```

1

コードの修正

2018/09/27 12:15

投稿

nekome4
nekome4

スコア24

title CHANGED
File without changes
body CHANGED
@@ -14,7 +14,7 @@
14
14
 
15
15
  public class CustomControl1 : TextBox
16
16
  {
17
- private static readonly DependencyProperty FooProperty = DependencyProperty.Register(
17
+ public static readonly DependencyProperty FooProperty = DependencyProperty.Register(
18
18
  "Foo", typeof(Hoge),
19
19
  new FrameworkPropertyMetadata(
20
20
  new Hoge(1, 1),