質問編集履歴

5

コンパイルが通らない問題を解決しました

2019/06/14 12:55

投稿

arw.tyx-out_mz
arw.tyx-out_mz

スコア27

test CHANGED
File without changes
test CHANGED
@@ -30,230 +30,414 @@
30
30
 
31
31
  ```C#
32
32
 
33
+ using System;
34
+
33
- public sealed class PersonList : BindableBase
35
+ using System.Collections.Generic;
36
+
37
+ using System.Linq;
38
+
39
+ using System.Text;
40
+
41
+ using System.Threading.Tasks;
42
+
43
+ using Prism.Mvvm;
44
+
45
+ using Reactive.Bindings;
46
+
47
+
48
+
49
+ namespace ForTeratail.Models
34
50
 
35
51
  {
36
52
 
37
- private static readonly PersonList m_instance = new PersonList();
53
+ public sealed class PersonList : BindableBase
38
-
39
-
40
-
41
- private PersonList()
42
54
 
43
55
  {
44
56
 
57
+ static readonly PersonList m_instance = new PersonList();
58
+
59
+
60
+
61
+ public static PersonList Instance
62
+
63
+ {
64
+
65
+ get { return m_instance; }
66
+
67
+ }
68
+
69
+
70
+
71
+ int count;
72
+
73
+
74
+
75
+ private PersonList()
76
+
77
+ {
78
+
79
+ count = 0;
80
+
45
- PersonCollection = new ReactiveCollection<Person>();
81
+ PersonCollection = new ReactiveCollection<Person>();
46
-
82
+
47
- Add();
83
+ Add();
84
+
85
+ }
86
+
87
+
88
+
89
+ ReactiveCollection<Person> m_collection;
90
+
91
+ public ReactiveCollection<Person> PersonCollection
92
+
93
+ {
94
+
95
+ get { return m_collection; }
96
+
97
+ set { SetProperty(ref m_collection, value); }
98
+
99
+ }
100
+
101
+
102
+
103
+ Person m_current;
104
+
105
+ public Person CurrentPerson
106
+
107
+ {
108
+
109
+ get { return m_current; }
110
+
111
+ set { SetProperty(ref m_current, value); }
112
+
113
+ }
114
+
115
+
116
+
117
+ public void Add()
118
+
119
+ {
120
+
121
+ Person p = new Person(count);
122
+
123
+ PersonCollection.Add(p);
124
+
125
+ CurrentPerson = PersonCollection[PersonCollection.Count - 1];
126
+
127
+ count++;
128
+
129
+ }
48
130
 
49
131
  }
50
132
 
133
+ }
134
+
135
+ ```
136
+
137
+
138
+
139
+ #### Person
140
+
141
+
142
+
143
+ ```C#
144
+
51
- public static PersonList Instance { get { return m_instance; } }
145
+ using System;
52
-
53
-
54
-
146
+
55
- ReactiveCollection<Person> m_collection;
147
+ using System.Collections.Generic;
148
+
56
-
149
+ using System.Linq;
150
+
151
+ using System.Text;
152
+
153
+ using System.Threading.Tasks;
154
+
155
+ using Prism.Mvvm;
156
+
157
+ using Reactive.Bindings;
158
+
159
+
160
+
161
+ namespace ForTeratail.Models
162
+
163
+ {
164
+
57
- public ReactiveCollection<Person> PersonCollection
165
+ public class Person : BindableBase
58
166
 
59
167
  {
60
168
 
169
+ public int Id { get; set; }
170
+
171
+
172
+
173
+ string m_name;
174
+
175
+ public string Name
176
+
177
+ {
178
+
61
- get { return m_collection; }
179
+ get { return m_name; }
62
-
180
+
63
- set { SetProperty(ref m_collection, value); }
181
+ set { SetProperty(ref m_name, value); }
182
+
183
+ }
184
+
185
+
186
+
187
+ int m_age;
188
+
189
+ public int Age
190
+
191
+ {
192
+
193
+ get { return m_age; }
194
+
195
+ set { SetProperty(ref m_age, value); }
196
+
197
+ }
198
+
199
+
200
+
201
+ public Person(int id)
202
+
203
+ {
204
+
205
+ Id = id;
206
+
207
+ }
64
208
 
65
209
  }
66
210
 
67
-
211
+ }
212
+
68
-
213
+ ```
214
+
215
+
216
+
217
+
218
+
219
+ #### MyViewModel(ComboBoxがあるViewのVM)
220
+
221
+
222
+
223
+ ```C#
224
+
225
+ using System.Reactive.Linq;
226
+
69
- Person m_current;
227
+ using Prism.Mvvm;
228
+
70
-
229
+ using Reactive.Bindings;
230
+
231
+ using Reactive.Bindings.Extensions;
232
+
71
- public Person CurrentPerson
233
+ using ForTeratail.Models;
234
+
235
+
236
+
237
+ namespace ForTeratail.ViewModels
238
+
239
+ {
240
+
241
+ public class MainWindowViewModel : BindableBase
72
242
 
73
243
  {
74
244
 
245
+ private string _title = "Prism Application";
246
+
247
+ public string Title
248
+
249
+ {
250
+
75
- get { return m_current; }
251
+ get { return _title; }
76
-
252
+
77
- set { SetProperty(ref m_current, value); }
253
+ set { SetProperty(ref _title, value); }
254
+
255
+ }
256
+
257
+
258
+
259
+ public ReactiveCollection<Person> Collection { get; }
260
+
261
+ public ReactiveProperty<Person> CurrentPerson { get; }
262
+
263
+ public ReactiveProperty<string> HereName { get; }
264
+
265
+ public ReactiveProperty<int> HereAge { get; }
266
+
267
+ public ReactiveProperty<string> Introduction { get; }
268
+
269
+
270
+
271
+ public ReactiveCommand<string> UIInteractiveNameCommand { get; }
272
+
273
+ public ReactiveCommand<int> UIInteractiveAgeCommand { get; }
274
+
275
+ public ReactiveCommand AddCommand { get; }
276
+
277
+
278
+
279
+ public MainWindowViewModel()
280
+
281
+ {
282
+
283
+ Collection = PersonList.Instance.PersonCollection;
284
+
285
+ CurrentPerson = PersonList.Instance.ToReactivePropertyAsSynchronized(x => x.CurrentPerson);
286
+
287
+
288
+
289
+ HereName = CurrentPerson.Select(x => x.Name).ToReactiveProperty();
290
+
291
+ HereAge = CurrentPerson.Select(x => x.Age).ToReactiveProperty();
292
+
293
+
294
+
295
+ Introduction = HereName.Where(x => x != null).Select(x => "I am " + x).ToReactiveProperty();
296
+
297
+
298
+
299
+ UIInteractiveNameCommand = new ReactiveCommand<string>().WithSubscribe(x =>
300
+
301
+ {
302
+
303
+ CurrentPerson.Value.Name = x;
304
+
305
+ });
306
+
307
+
308
+
309
+ UIInteractiveAgeCommand = new ReactiveCommand<int>().WithSubscribe(x =>
310
+
311
+ {
312
+
313
+ CurrentPerson.Value.Age = x;
314
+
315
+ });
316
+
317
+
318
+
319
+ AddCommand = new ReactiveCommand();
320
+
321
+ AddCommand.Subscribe(PersonList.Instance.Add);
322
+
323
+ }
78
324
 
79
325
  }
80
326
 
81
-
82
-
83
- public void Add()
84
-
85
- {
86
-
87
- Person p = new Person();
88
-
89
- PersonCollection.Add(p);
90
-
91
- CurrentPerson = PersonCollection[PersonCollection.Count - 1];
92
-
93
- }
94
-
95
327
  }
96
328
 
97
329
  ```
98
330
 
99
331
 
100
332
 
101
- #### Person
333
+ #### MyView (ComboBoxがあるView)
102
334
 
103
335
 
104
336
 
105
337
  ```C#
106
338
 
107
- public class Person : BindableBase
339
+ <Window x:Class="ForTeratail.Views.MainWindow"
108
-
109
- {
340
+
110
-
111
- string m_name;
341
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
112
-
342
+
113
- public string Name
343
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
114
-
115
- {
344
+
116
-
117
- get { return m_name; }
345
+ xmlns:prism="http://prismlibrary.com/"
118
-
346
+
119
- set { SetProperty(ref m_name, value); }
347
+ prism:ViewModelLocator.AutoWireViewModel="True"
120
-
348
+
121
- }
349
+ Title="{Binding Title}" Height="350" Width="525">
122
-
123
-
124
-
350
+
125
- int m_age;
351
+ <Grid>
352
+
126
-
353
+ <Grid.RowDefinitions>
354
+
355
+ <RowDefinition/>
356
+
357
+ <RowDefinition/>
358
+
359
+ <RowDefinition/>
360
+
361
+ <RowDefinition/>
362
+
363
+ </Grid.RowDefinitions>
364
+
365
+ <Grid.ColumnDefinitions>
366
+
367
+ <ColumnDefinition/>
368
+
369
+ <ColumnDefinition/>
370
+
371
+ </Grid.ColumnDefinitions>
372
+
373
+ <ComboBox Grid.Column="0" Margin="10 20"
374
+
375
+ ItemsSource="{Binding Collection}"
376
+
377
+ SelectedValue="{Binding CurrentPerson.Value}"
378
+
379
+ DisplayMemberPath="Id" />
380
+
381
+ <Button Grid.Column="1" Content="新規追加" Command="{Binding AddCommand}" Margin="20" />
382
+
383
+
384
+
385
+ <TextBox Grid.Row="1" Grid.Column="0" Margin="10" Height="30" FontSize="18"
386
+
387
+ TextAlignment="Center" VerticalContentAlignment="Center"
388
+
389
+ x:Name="NameBlock"/>
390
+
391
+ <Button Grid.Row="1" Grid.Column="1" Content="登録" Margin="20"
392
+
393
+ Command="{Binding UIInteractiveNameCommand}"
394
+
395
+ CommandParameter="{Binding Text, ElementName=NameBlock}" />
396
+
397
+
398
+
399
+ <TextBox Grid.Row="2" Grid.Column="0" Margin="10" Height="30" FontSize="18"
400
+
401
+ TextAlignment="Center" VerticalContentAlignment="Center"
402
+
403
+ x:Name="AgeBlock"/>
404
+
405
+ <Button Grid.Row="2" Grid.Column="1" Content="登録" Margin="20"
406
+
407
+ Command="{Binding UIInteractiveAgeCommand}"
408
+
409
+ CommandParameter="{Binding Text, ElementName=AgeBlock}" />
410
+
411
+
412
+
413
+ <Label Grid.Row="3" Grid.ColumnSpan="2" Content="{Binding Introduction.Value}" />
414
+
127
- public int Age
415
+ </Grid>
128
-
129
- {
416
+
130
-
131
- get { return m_age; }
417
+ </Window>
132
-
133
- set { SetProperty(ref m_age, value); }
134
-
135
- }
136
-
137
- }
138
418
 
139
419
  ```
140
420
 
141
421
 
142
422
 
143
-
144
-
145
- #### MyViewModel(ComboBoxがあるViewのVM)
146
-
147
-
148
-
149
- ```C#
423
+ ### 問題
150
-
151
- class MyViewModel : BindableBase
424
+
152
-
153
- {
154
-
155
- public ReactiveCollection<Person> Collection { get; }
156
-
157
- public ReactiveProperty<Person> CurrentPerson { get; }
158
-
159
- public ReactiveProperty<string> HereName { get; }
160
-
161
- public ReactiveProperty<int> HereAge { get; }
162
-
163
- public ReactiveProperty<string> Introduction { get; }
164
-
165
-
166
-
167
- public ReactiveCommand<string> UIInteractiveNameCommand { get; }
168
-
169
- public ReactiveCommand<int> UIInteractiveAgeCommand { get; }
170
-
171
- public ReactiveCommand AddCommand { get; }
172
-
173
-
174
-
175
- public MyViewModel()
176
-
177
- {
178
-
179
- // ComboBoxで表示されるリスト
180
-
181
- Collection = PersonList.Instance.PersonCollection;
425
+ 新規追加ボタンを押すと`PersonList`クラスの`PersonCollection`に空の`Person`オブジェクトが追加されます.
182
-
426
+
183
- // ComboBoxで現在選択されているリスト
427
+ それがComboBoxに紐付いています.
428
+
184
-
429
+ また,登録ボタンを押すとテキストボックスにあるテキストがCommandの引数として渡され,現在選択されている`Person`オブジェクトのプロパティとしてセットされます.
430
+
185
- CurrentPerson = PersonList.Instance.ToReactivePropertyAsSynchronized(x => x.CurrentPerson);
431
+ ここはあくまで発生している問題を再現する簡易的な例なので,TextBoxの内容を`ReactiveProperty`とBindingするということは考えないでください.
186
-
187
-
188
-
432
+
189
- HereName = CurrentPerson.Select(x => x.Name).ToReactiveProperty(); // => こがずっnullになる
433
+ あくまで,コマンド経由で現在選択されているオブジェクトのプロパティを変更したときに,それを監視している`ReactiveProperty`の値が変更さないいう問題です.
190
-
191
- HereAge = CurrentPerson.Select(x => x.Age).ToReactiveProperty(); // => これがずっとnullになる
192
-
193
-
194
-
195
- // このプロパティはCurrentPersonの変更と,CurrentPerson.Value.Nameの変更の両方を検知したい
196
-
197
- Introduction = HereName.Where(x => x != null).Select(x => "I am " + x).ToReactiveProperty();
198
-
199
-
200
-
201
- UIInteractiveNameCommand = new ReactiveCommand<string>().WithSubscribe(x =>
202
-
203
- {
204
-
205
- CurrentPerson.Name = x;
206
-
207
- });
208
-
209
-
210
-
211
- UIInteractiveAgeCommand = new ReactiveCommand<int>().WithSubscribe(x =>
212
-
213
- {
214
-
215
- CurrentPerson.Age = x;
216
-
217
- });
218
-
219
-
220
-
221
- // AddされるとCurrentPersonが変化する
222
-
223
- // そのときにHereNameの値が更新されない
224
-
225
- AddCommand = new ReactiveCommand().WithSubscribe(_ => PersonList.Instance.Add());
226
-
227
- }
228
-
229
- }
230
-
231
- ```
232
-
233
-
234
-
235
- #### MyView (ComboBoxがあるView)
236
-
237
-
238
-
239
- ```C#
240
-
241
- // 省略
242
-
243
- <ComboBox ItemsSource="{Binding Collection}" SelectedValue="{Binding CurrentPerson.Value}" DisplayMemberPath="Name"
244
-
245
- Grid.Row="2" Grid.Column="0" Margin="0 0"/>
246
-
247
- <Button Command="{Binding AddCommand}" />
248
-
249
- // 省略
250
-
251
- ```
252
434
 
253
435
 
254
436
 
255
437
  上記クラスの`CurrentPerson`の`Name`プロパティや`Age`プロパティは適切に変更されますが,`HereName`や`HereAge`が`null`のままで書き換わってくれません.
256
438
 
439
+ しかし,ComboBoxで選択しているオブジェクトを変更し(例えば`Id=0`のオブジェクトから`Id=1`のオブジェクトへ),その後同じオブジェクト(`Id=0`)に戻ってくると,プロパティの値がちゃんと`Here〇〇`に設定されています.
440
+
257
441
  `CurrentPerson`が保持している`Person`オブジェクト自体の変更と,その`Person`オブジェクト内のプロパティ両方の変更を検知するためにはどのように修正すればいいでしょうか?
258
442
 
259
443
 

4

ソースコードの修正

2019/06/14 12:55

投稿

arw.tyx-out_mz
arw.tyx-out_mz

スコア27

test CHANGED
File without changes
test CHANGED
@@ -160,6 +160,8 @@
160
160
 
161
161
  public ReactiveProperty<int> HereAge { get; }
162
162
 
163
+ public ReactiveProperty<string> Introduction { get; }
164
+
163
165
 
164
166
 
165
167
  public ReactiveCommand<string> UIInteractiveNameCommand { get; }
@@ -190,6 +192,12 @@
190
192
 
191
193
 
192
194
 
195
+ // このプロパティはCurrentPersonの変更と,CurrentPerson.Value.Nameの変更の両方を検知したい
196
+
197
+ Introduction = HereName.Where(x => x != null).Select(x => "I am " + x).ToReactiveProperty();
198
+
199
+
200
+
193
201
  UIInteractiveNameCommand = new ReactiveCommand<string>().WithSubscribe(x =>
194
202
 
195
203
  {

3

ソースコード及びやりたいことの追記

2019/06/14 02:43

投稿

arw.tyx-out_mz
arw.tyx-out_mz

スコア27

test CHANGED
File without changes
test CHANGED
@@ -8,11 +8,13 @@
8
8
 
9
9
 
10
10
 
11
- # 問題
11
+ # やりたいこと
12
-
13
-
14
-
12
+
13
+
14
+
15
- ある自作クラスの`ReactiveProperty`と,そのクラスのプロパティの`ReactiveProperty`を作っています.
15
+ ある自作クラスの`ReactiveProperty`Aと,そのクラスのプロパティの`ReactiveProperty`Bを作っています.
16
+
17
+ Bにおいて,`A.Value`と,その`A.Value.Property`の両方を監視したいです.
16
18
 
17
19
  自作クラスの`ReactiveProperty`を書換えたときに,連動してプロパティの`ReactiveProperty`も書き換わってほしいのですが,ずっとnullのままです.
18
20
 
@@ -118,6 +120,20 @@
118
120
 
119
121
  }
120
122
 
123
+
124
+
125
+ int m_age;
126
+
127
+ public int Age
128
+
129
+ {
130
+
131
+ get { return m_age; }
132
+
133
+ set { SetProperty(ref m_age, value); }
134
+
135
+ }
136
+
121
137
  }
122
138
 
123
139
  ```
@@ -142,7 +158,15 @@
142
158
 
143
159
  public ReactiveProperty<string> HereName { get; }
144
160
 
161
+ public ReactiveProperty<int> HereAge { get; }
162
+
163
+
164
+
145
- public ReactiveCommand<string> UIInteractiveCommand { get; }
165
+ public ReactiveCommand<string> UIInteractiveNameCommand { get; }
166
+
167
+ public ReactiveCommand<int> UIInteractiveAgeCommand { get; }
168
+
169
+ public ReactiveCommand AddCommand { get; }
146
170
 
147
171
 
148
172
 
@@ -150,21 +174,47 @@
150
174
 
151
175
  {
152
176
 
177
+ // ComboBoxで表示されるリスト
178
+
153
179
  Collection = PersonList.Instance.PersonCollection;
154
180
 
181
+ // ComboBoxで現在選択されているリスト
182
+
155
183
  CurrentPerson = PersonList.Instance.ToReactivePropertyAsSynchronized(x => x.CurrentPerson);
156
184
 
185
+
186
+
157
187
  HereName = CurrentPerson.Select(x => x.Name).ToReactiveProperty(); // => これがずっとnullになる
158
188
 
159
-
189
+ HereAge = CurrentPerson.Select(x => x.Age).ToReactiveProperty(); // => これがずっとnullになる
160
-
190
+
191
+
192
+
161
- UIInteractiveCommand = new ReactiveCommand<string>().WithSubscribe(x =>
193
+ UIInteractiveNameCommand = new ReactiveCommand<string>().WithSubscribe(x =>
162
194
 
163
195
  {
164
196
 
165
- CurrentPerson.Value.Name = x;
197
+ CurrentPerson.Name = x;
166
-
198
+
167
- })
199
+ });
200
+
201
+
202
+
203
+ UIInteractiveAgeCommand = new ReactiveCommand<int>().WithSubscribe(x =>
204
+
205
+ {
206
+
207
+ CurrentPerson.Age = x;
208
+
209
+ });
210
+
211
+
212
+
213
+ // AddされるとCurrentPersonが変化する
214
+
215
+ // そのときにHereNameの値が更新されない
216
+
217
+ AddCommand = new ReactiveCommand().WithSubscribe(_ => PersonList.Instance.Add());
168
218
 
169
219
  }
170
220
 
@@ -174,9 +224,29 @@
174
224
 
175
225
 
176
226
 
227
+ #### MyView (ComboBoxがあるView)
228
+
229
+
230
+
231
+ ```C#
232
+
233
+ // 省略
234
+
235
+ <ComboBox ItemsSource="{Binding Collection}" SelectedValue="{Binding CurrentPerson.Value}" DisplayMemberPath="Name"
236
+
237
+ Grid.Row="2" Grid.Column="0" Margin="0 0"/>
238
+
239
+ <Button Command="{Binding AddCommand}" />
240
+
241
+ // 省略
242
+
243
+ ```
244
+
245
+
246
+
177
- 上記クラスの`CurrentPerson`の`Name`プロパティは適切に変更されますが,`HereName`が`null`のままで書き換わってくれません.
247
+ 上記クラスの`CurrentPerson`の`Name`プロパティや`Age`プロパティは適切に変更されますが,`HereName`や`HereAge`が`null`のままで書き換わってくれません.
178
-
248
+
179
- どのように修正すればいいでしょうか?
249
+ `CurrentPerson`が保持している`Person`オブジェクト自体の変更と,その`Person`オブジェクト内のプロパティ両方の変更を検知するためにはどのように修正すればいいでしょうか?
180
250
 
181
251
 
182
252
 

2

ソースコードの修正を行いました.

2019/06/14 02:36

投稿

arw.tyx-out_mz
arw.tyx-out_mz

スコア27

test CHANGED
File without changes
test CHANGED
@@ -162,7 +162,7 @@
162
162
 
163
163
  {
164
164
 
165
- CurrentPerson.Name = x;
165
+ CurrentPerson.Value.Name = x;
166
166
 
167
167
  })
168
168
 

1

ソースコードの修正を行いました.

2019/06/13 14:05

投稿

arw.tyx-out_mz
arw.tyx-out_mz

スコア27

test CHANGED
File without changes
test CHANGED
@@ -28,9 +28,27 @@
28
28
 
29
29
  ```C#
30
30
 
31
- sealed class PersonList : BindableBase
31
+ public sealed class PersonList : BindableBase
32
32
 
33
33
  {
34
+
35
+ private static readonly PersonList m_instance = new PersonList();
36
+
37
+
38
+
39
+ private PersonList()
40
+
41
+ {
42
+
43
+ PersonCollection = new ReactiveCollection<Person>();
44
+
45
+ Add();
46
+
47
+ }
48
+
49
+ public static PersonList Instance { get { return m_instance; } }
50
+
51
+
34
52
 
35
53
  ReactiveCollection<Person> m_collection;
36
54
 
@@ -58,6 +76,20 @@
58
76
 
59
77
  }
60
78
 
79
+
80
+
81
+ public void Add()
82
+
83
+ {
84
+
85
+ Person p = new Person();
86
+
87
+ PersonCollection.Add(p);
88
+
89
+ CurrentPerson = PersonCollection[PersonCollection.Count - 1];
90
+
91
+ }
92
+
61
93
  }
62
94
 
63
95
  ```
@@ -70,7 +102,7 @@
70
102
 
71
103
  ```C#
72
104
 
73
- class Person : BindableBase
105
+ public class Person : BindableBase
74
106
 
75
107
  {
76
108
 
@@ -142,7 +174,7 @@
142
174
 
143
175
 
144
176
 
145
- 上記クラスの`CurrentPerson`の中の`Name`プロパティは適切に変更されますが,`HereName`が`null`のままで書き換わってくれません.
177
+ 上記クラスの`CurrentPerson`の`Name`プロパティは適切に変更されますが,`HereName`が`null`のままで書き換わってくれません.
146
178
 
147
179
  どのように修正すればいいでしょうか?
148
180