回答編集履歴
3
見直しキャンペーン中
test
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
動くコードがないと話をすり合わせるのが大変なので^^;
|
2
|
-
今の私の理解を
|
2
|
+
今の私の理解をMVVMを意識せずざっくり実装しました。
|
3
3
|
|
4
4
|
```xml:MainWindow.xaml
|
5
5
|
<Window
|
2
見直しキャンペーン中
test
CHANGED
@@ -1,413 +1,203 @@
|
|
1
1
|
動くコードがないと話をすり合わせるのが大変なので^^;
|
2
|
-
|
3
2
|
今の私の理解を`MVVM`を意識せずざっくり実装しました。
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
MainWindow.xaml
|
4
|
+
```xml:MainWindow.xaml
|
8
|
-
|
9
|
-
```xaml
|
10
|
-
|
11
5
|
<Window
|
12
|
-
|
13
6
|
x:Class="Test.MainWindow"
|
14
|
-
|
15
7
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
16
|
-
|
17
8
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
18
|
-
|
19
9
|
xmlns:local="clr-namespace:Test"
|
20
|
-
|
21
10
|
Height="450"
|
22
|
-
|
23
11
|
SizeToContent="Width">
|
24
|
-
|
25
12
|
<Window.DataContext>
|
26
|
-
|
27
13
|
<local:MainWindowViewModel />
|
28
|
-
|
29
14
|
</Window.DataContext>
|
30
|
-
|
31
15
|
<Window.Resources>
|
32
|
-
|
33
16
|
<DataTemplate x:Key="CheckedInfo" DataType="{x:Type local:Info}">
|
34
|
-
|
35
17
|
<TextBlock Text="{Binding Path=Name, StringFormat=CheckedInfo: {0}}" />
|
36
|
-
|
37
18
|
</DataTemplate>
|
38
|
-
|
39
19
|
</Window.Resources>
|
40
|
-
|
41
20
|
<Grid>
|
42
|
-
|
43
21
|
<Grid.RowDefinitions>
|
44
|
-
|
45
22
|
<RowDefinition />
|
46
|
-
|
47
23
|
<RowDefinition Height="2*" />
|
48
|
-
|
49
24
|
</Grid.RowDefinitions>
|
50
|
-
|
51
25
|
<ListBox ItemTemplate="{StaticResource CheckedInfo}" ItemsSource="{Binding Path=CheckedInfoList, ElementName=testControl}" />
|
52
|
-
|
53
26
|
<local:TestControl
|
54
|
-
|
55
27
|
x:Name="testControl"
|
56
|
-
|
57
28
|
Grid.Row="1"
|
58
|
-
|
59
29
|
InfoList="{Binding Path=InfoList}" />
|
60
|
-
|
61
30
|
</Grid>
|
62
|
-
|
63
31
|
</Window>
|
64
|
-
|
65
|
-
```
|
32
|
+
```
|
66
|
-
|
67
|
-
|
68
|
-
|
33
|
+
|
69
|
-
MainWindowViewModel.cs
|
34
|
+
```cs:MainWindowViewModel.cs
|
70
|
-
|
71
|
-
```C#
|
72
|
-
|
73
35
|
using System.Collections.Generic;
|
74
36
|
|
75
|
-
|
76
|
-
|
77
37
|
namespace Test
|
78
|
-
|
79
38
|
{
|
80
|
-
|
81
39
|
public class MainWindowViewModel //: Observable
|
82
|
-
|
83
40
|
{
|
84
|
-
|
85
41
|
public InfoList InfoList { get; }
|
86
42
|
|
87
|
-
|
88
|
-
|
89
43
|
//private InfoList _CheckedInfoList;
|
90
|
-
|
91
44
|
//public InfoList CheckedInfoList { get => _CheckedInfoList; set => Set(ref _CheckedInfoList, value); }
|
92
45
|
|
93
|
-
|
94
|
-
|
95
46
|
public MainWindowViewModel()
|
96
|
-
|
97
|
-
{
|
47
|
+
{
|
98
|
-
|
99
48
|
InfoList = new InfoList
|
100
|
-
|
101
49
|
{
|
102
|
-
|
103
50
|
new Info {
|
104
|
-
|
105
51
|
Name = "1",
|
106
|
-
|
107
52
|
Child = new InfoList {
|
108
|
-
|
109
53
|
new Info {
|
110
|
-
|
111
54
|
Name = "1-1",
|
112
|
-
|
113
55
|
Child = new InfoList {
|
114
|
-
|
115
56
|
new Info { Name = "1-1-1", Check = true, },
|
116
|
-
|
117
57
|
new Info { Name = "1-1-2", },
|
118
|
-
|
119
58
|
},
|
120
|
-
|
121
59
|
},
|
122
|
-
|
123
60
|
},
|
124
|
-
|
125
61
|
},
|
126
|
-
|
127
62
|
new Info {
|
128
|
-
|
129
63
|
Name = "2",
|
130
|
-
|
131
64
|
Child = new InfoList {
|
132
|
-
|
133
65
|
new Info { Name = "2-1", Check = true, },
|
134
|
-
|
135
66
|
},
|
136
|
-
|
137
67
|
},
|
138
|
-
|
139
68
|
new Info { Name = "3", Check = true, },
|
140
|
-
|
141
69
|
new Info {
|
142
|
-
|
143
70
|
Name = "4",
|
144
|
-
|
145
71
|
Child = new InfoList {
|
146
|
-
|
147
72
|
new Info { Name = "4-1", },
|
148
|
-
|
149
73
|
},
|
150
|
-
|
151
74
|
},
|
152
|
-
|
153
75
|
};
|
154
|
-
|
155
|
-
}
|
76
|
+
}
|
156
|
-
|
157
77
|
}
|
158
78
|
|
159
|
-
|
160
|
-
|
161
79
|
public class InfoList : List<Info> { }
|
162
80
|
|
163
|
-
|
164
|
-
|
165
81
|
public class Info
|
166
|
-
|
167
82
|
{
|
168
|
-
|
169
83
|
public string Name { get; set; }
|
170
|
-
|
171
84
|
//public string Icon { get; set; }
|
172
|
-
|
173
85
|
public bool Expand { get; set; } = true;
|
174
|
-
|
175
86
|
public bool Check { get; set; }
|
176
87
|
|
177
|
-
|
178
|
-
|
179
88
|
public InfoList Child { get; set; } // Info Child?
|
180
|
-
|
181
89
|
}
|
182
|
-
|
183
90
|
}
|
184
|
-
|
185
|
-
```
|
91
|
+
```
|
186
|
-
|
187
|
-
|
188
|
-
|
92
|
+
|
189
|
-
TestControl.xaml
|
93
|
+
```xml:TestControl.xaml
|
190
|
-
|
191
|
-
```xaml
|
192
|
-
|
193
94
|
<UserControl
|
194
|
-
|
195
95
|
x:Class="Test.TestControl"
|
196
|
-
|
197
96
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
198
|
-
|
199
97
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
200
|
-
|
201
98
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
202
|
-
|
203
99
|
xmlns:local="clr-namespace:Test"
|
204
|
-
|
205
100
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
206
|
-
|
207
101
|
x:Name="userControl"
|
208
|
-
|
209
102
|
Width="300"
|
210
|
-
|
211
103
|
d:DesignHeight="400"
|
212
|
-
|
213
104
|
mc:Ignorable="d">
|
214
|
-
|
215
105
|
<Grid Name="baseContainer">
|
216
|
-
|
217
106
|
<TreeView
|
218
|
-
|
219
107
|
CheckBox.Checked="TreeView_CheckChanged"
|
220
|
-
|
221
108
|
CheckBox.Unchecked="TreeView_CheckChanged"
|
222
|
-
|
223
109
|
ItemsSource="{Binding InfoList, ElementName=userControl, Mode=OneWay}">
|
224
|
-
|
225
110
|
<TreeView.Resources>
|
226
|
-
|
227
111
|
<Style TargetType="TreeViewItem">
|
228
|
-
|
229
112
|
<Setter Property="IsExpanded" Value="{Binding Path=Expand, Mode=TwoWay}" />
|
230
|
-
|
231
113
|
</Style>
|
232
|
-
|
233
114
|
</TreeView.Resources>
|
234
115
|
|
235
|
-
|
236
|
-
|
237
116
|
<TreeView.ItemTemplate>
|
238
|
-
|
239
117
|
<HierarchicalDataTemplate DataType="local:InfoList" ItemsSource="{Binding Path=Child}">
|
240
|
-
|
241
118
|
<StackPanel Orientation="Horizontal">
|
242
|
-
|
243
119
|
<CheckBox IsChecked="{Binding Path=Check, Mode=TwoWay}" />
|
244
|
-
|
245
120
|
<!--<Image Source="{Binding Path=Icon}" />-->
|
246
|
-
|
247
121
|
<TextBlock Text="{Binding Path=Name}" />
|
248
|
-
|
249
122
|
</StackPanel>
|
250
|
-
|
251
123
|
</HierarchicalDataTemplate>
|
252
|
-
|
253
124
|
</TreeView.ItemTemplate>
|
254
|
-
|
255
125
|
</TreeView>
|
256
|
-
|
257
126
|
</Grid>
|
258
|
-
|
259
127
|
</UserControl>
|
260
|
-
|
261
|
-
```
|
128
|
+
```
|
262
|
-
|
263
|
-
|
264
|
-
|
129
|
+
|
265
|
-
TestControl.xaml.cs
|
130
|
+
```cs:TestControl.xaml.cs
|
266
|
-
|
267
|
-
```C#
|
268
|
-
|
269
131
|
using System.Windows;
|
270
|
-
|
271
132
|
using System.Windows.Controls;
|
272
133
|
|
273
|
-
|
274
|
-
|
275
134
|
namespace Test
|
276
|
-
|
277
135
|
{
|
278
|
-
|
279
136
|
public partial class TestControl : UserControl
|
280
|
-
|
281
137
|
{
|
282
|
-
|
283
138
|
public static readonly DependencyProperty InfoListProperty
|
284
|
-
|
285
139
|
= DependencyProperty.Register(nameof(InfoList), typeof(InfoList),
|
286
|
-
|
287
140
|
typeof(TestControl), new PropertyMetadata(null));
|
288
|
-
|
289
141
|
public InfoList InfoList
|
290
|
-
|
291
|
-
{
|
142
|
+
{
|
292
|
-
|
293
143
|
get => (InfoList)GetValue(InfoListProperty);
|
294
|
-
|
295
144
|
set => SetValue(InfoListProperty, value);
|
296
|
-
|
297
|
-
}
|
145
|
+
}
|
298
|
-
|
299
|
-
|
300
146
|
|
301
147
|
public static readonly DependencyProperty CheckedInfoListProperty
|
302
|
-
|
303
148
|
= DependencyProperty.Register(nameof(CheckedInfoList), typeof(InfoList),
|
304
|
-
|
305
149
|
typeof(TestControl), new PropertyMetadata(null));
|
306
|
-
|
307
150
|
public InfoList CheckedInfoList
|
308
|
-
|
309
|
-
{
|
151
|
+
{
|
310
|
-
|
311
152
|
get => (InfoList)GetValue(CheckedInfoListProperty);
|
312
|
-
|
313
153
|
set => SetValue(CheckedInfoListProperty, value);
|
314
|
-
|
315
|
-
}
|
154
|
+
}
|
316
|
-
|
317
|
-
|
318
|
-
|
319
155
|
|
320
156
|
|
321
157
|
public TestControl()
|
322
|
-
|
323
|
-
{
|
158
|
+
{
|
324
|
-
|
325
159
|
InitializeComponent();
|
326
|
-
|
327
|
-
}
|
160
|
+
}
|
328
|
-
|
329
|
-
|
330
161
|
|
331
162
|
private void TreeView_CheckChanged(object sender, RoutedEventArgs e)
|
332
|
-
|
333
|
-
{
|
163
|
+
{
|
334
|
-
|
335
164
|
var l = new InfoList();
|
336
|
-
|
337
165
|
foreach(var c in InfoList)
|
338
|
-
|
339
166
|
{
|
340
|
-
|
341
167
|
if(Dfs(c)) l.Add(c);
|
342
|
-
|
343
168
|
}
|
344
|
-
|
345
169
|
CheckedInfoList = l;
|
346
170
|
|
347
|
-
|
348
|
-
|
349
171
|
bool Dfs(Info info)
|
350
|
-
|
351
172
|
{
|
352
|
-
|
353
173
|
if(info.Check) return true;
|
354
|
-
|
355
174
|
if(info.Child == null) return false;
|
356
|
-
|
357
175
|
foreach(var c in info.Child)
|
358
|
-
|
359
176
|
{
|
360
|
-
|
361
177
|
if(Dfs(c)) return true;
|
362
|
-
|
363
178
|
}
|
364
179
|
|
365
|
-
|
366
|
-
|
367
180
|
return false;
|
368
|
-
|
369
181
|
}
|
370
|
-
|
371
|
-
}
|
182
|
+
}
|
372
|
-
|
373
183
|
}
|
374
|
-
|
375
184
|
}
|
376
|
-
|
377
|
-
```
|
185
|
+
```
|
378
|
-
|
379
186
|
![アプリ画像](380998da49d4578b09dbb91546c96fd7.png)
|
380
187
|
|
381
|
-
|
382
|
-
|
383
188
|
動作はこれでいいのでしょうか?
|
384
|
-
|
385
189
|
これですと`TestControl`にVMがありませんが、実際は`MainWindowViewModel`から渡された`InfoList`を`TestControl`で`InfoListVM`等に加工(詰め替え)しているということでしょうか?(何のために??)
|
386
|
-
|
387
190
|
それとも`Info`が`Check`・`Child`だけで(`Name`もか?)、`InfoVM`に`Icon`や`Expand`を生やしてるってことなのかな?
|
388
191
|
|
389
192
|
|
390
|
-
|
391
|
-
|
392
|
-
|
393
193
|
> データの実体はモデル部より供給
|
394
194
|
|
395
|
-
|
396
|
-
|
397
195
|
> check状態(開始時) App --> UserControl v --> vm --> model
|
398
|
-
|
399
196
|
> check状態(終了時) App <-- UserControl v <-- vm <-- model
|
400
|
-
|
401
197
|
> ツリー構造の実体 UserControl v <-- vm <-- model
|
402
198
|
|
403
|
-
|
404
|
-
|
405
199
|
このへんのニュアンスもいまいちわかりません。
|
406
|
-
|
407
200
|
モデルとは`CheckedInfoList`のことを指しているんでしょうか?
|
408
|
-
|
409
201
|
それとも`InfoVM`のために画像をとってくるような処理の部分?
|
410
202
|
|
411
|
-
|
412
|
-
|
413
203
|
もしもあまりに乖離しているようですと、VM・Mも出せる範囲で出していただかないと理解できそうにありません^^;
|
1
画像
test
CHANGED
@@ -376,6 +376,8 @@
|
|
376
376
|
|
377
377
|
```
|
378
378
|
|
379
|
+
![アプリ画像](380998da49d4578b09dbb91546c96fd7.png)
|
380
|
+
|
379
381
|
|
380
382
|
|
381
383
|
動作はこれでいいのでしょうか?
|