回答編集履歴

1

見直しキャンペーン中

2023/07/17 13:20

投稿

TN8001
TN8001

スコア9326

test CHANGED
@@ -1,425 +1,212 @@
1
- MVVMにこだわらないのであれば、
1
+ MVVMにこだわらないのであれば、こんな感じでどうでしょうか。
2
-
3
- ```xaml
2
+ ```xml
4
-
5
3
  <Window
6
-
7
4
  x:Class="WpfApp1.SubWindow"
8
-
9
5
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
10
-
11
6
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
12
-
13
7
  xmlns:local="clr-namespace:WpfApp1"
14
-
15
8
  Title="SubWindow"
16
-
17
9
  Width="800"
18
-
19
10
  Height="450">
20
-
21
11
  <Window.DataContext>
22
-
23
12
  <local:SubViewModel />
24
-
25
13
  </Window.DataContext>
26
-
27
14
  <Grid>
28
-
29
15
  <Grid.RowDefinitions>
30
-
31
16
  <RowDefinition />
32
-
33
17
  <RowDefinition />
34
-
35
18
  </Grid.RowDefinitions>
36
-
37
19
  <TextBox Text="{Binding Text}" />
38
-
39
20
  <Grid Grid.Row="1">
40
-
41
21
  <Grid.ColumnDefinitions>
42
-
43
22
  <ColumnDefinition />
44
-
45
23
  <ColumnDefinition />
46
-
47
24
  </Grid.ColumnDefinitions>
48
-
49
25
  <Button Content="Cancel" IsCancel="True" />
50
-
51
26
  <Button
52
-
53
27
  Grid.Column="1"
54
-
55
28
  Command="{Binding DoSomethingCommand}"
56
-
57
29
  CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
58
-
59
30
  Content="OK"
60
-
61
31
  IsDefault="True" />
62
-
63
32
  </Grid>
64
-
65
33
  </Grid>
66
-
67
34
  </Window>
68
-
69
- ```
35
+ ```
70
-
71
-
72
-
36
+
73
- ```C#
37
+ ```cs
74
-
75
38
  using System.Windows;
76
-
77
39
  using Prism.Commands;
78
40
 
79
-
80
-
81
41
  namespace WpfApp1
82
-
83
42
  {
84
-
85
43
  public class SubViewModel
86
-
87
44
  {
88
-
89
45
  public string Text { get; set; }
90
-
91
46
  public DelegateCommand<Window> DoSomethingCommand { get; }
92
47
 
93
-
94
-
95
48
  public SubViewModel()
96
-
97
49
  {
98
-
99
50
  DoSomethingCommand = new DelegateCommand<Window>((w) =>
100
-
101
51
  {
102
-
103
52
  System.Diagnostics.Debug.WriteLine("DoSomethigCommand");
104
53
 
105
-
106
-
107
54
  if(string.IsNullOrEmpty(Text))
108
-
109
55
  {
110
-
111
56
  MessageBox.Show("何か入力してください。");
112
-
113
57
  }
114
-
115
58
  else
116
-
117
59
  {
118
-
119
60
  w.DialogResult = true;
120
-
121
61
  }
122
-
123
62
  });
124
-
125
63
  }
126
-
127
64
  }
128
-
129
65
  }
130
-
131
- ```
66
+ ```
132
-
133
- こんな感じでどうでしょうか。
134
-
135
-
136
67
 
137
68
  ---
138
69
 
139
-
140
-
141
- 実際には入力値はもっとあってそれぞれ検証したいのであれば`INotifyDataErrorInfo`等を実装しエラーがあればボタンを押せなくするのがきれいかもしれません。
70
+ 実際には入力値はもっとあってそれぞれ検証したいのであれば`INotifyDataErrorInfo`等を実装しエラーがあればボタンを押せなくするのがきれいかもしれません。
142
-
143
-
144
-
71
+
145
- ```xaml
72
+ ```xml
146
-
147
73
  <Window
148
-
149
74
  x:Class="WpfApp1.SubWindow"
150
-
151
75
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
152
-
153
76
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
154
-
155
77
  xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
156
-
157
78
  xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
158
-
159
79
  xmlns:local="clr-namespace:WpfApp1"
160
-
161
80
  Name="SubWnd"
162
-
163
81
  Title="SubWindow"
164
-
165
82
  Width="800"
166
-
167
83
  Height="450">
168
-
169
84
  <Window.Resources>
170
-
171
85
  <ControlTemplate x:Key="ValidationTemplate">
172
-
173
86
  <StackPanel>
174
-
175
87
  <ItemsControl HorizontalAlignment="Right" ItemsSource="{Binding AdornedElement.(Validation.Errors), ElementName=validationTarget}">
176
-
177
88
  <ItemsControl.ItemTemplate>
178
-
179
89
  <DataTemplate>
180
-
181
90
  <TextBlock Foreground="Red" Text="{Binding ErrorContent}" />
182
-
183
91
  </DataTemplate>
184
-
185
92
  </ItemsControl.ItemTemplate>
186
-
187
93
  </ItemsControl>
188
-
189
94
  <AdornedElementPlaceholder x:Name="validationTarget" />
190
-
191
95
  </StackPanel>
192
-
193
96
  </ControlTemplate>
194
-
195
97
  </Window.Resources>
196
-
197
98
  <Window.DataContext>
198
-
199
99
  <local:SubViewModel />
200
-
201
100
  </Window.DataContext>
202
-
203
101
  <DockPanel>
204
-
205
102
  <StackPanel
206
-
207
103
  HorizontalAlignment="Right"
208
-
209
104
  DockPanel.Dock="Bottom"
210
-
211
105
  Orientation="Horizontal">
212
-
213
106
  <Button
214
-
215
107
  MinWidth="80"
216
-
217
108
  Margin="5"
218
-
219
109
  Command="{Binding DoSomethingCommand}"
220
-
221
110
  Content="OK">
222
-
223
111
  <i:Interaction.Triggers>
224
-
225
112
  <i:EventTrigger EventName="Click">
226
-
227
113
  <ei:ChangePropertyAction
228
-
229
114
  PropertyName="DialogResult"
230
-
231
115
  TargetObject="{Binding ElementName=SubWnd}"
232
-
233
116
  Value="True" />
234
-
235
117
  </i:EventTrigger>
236
-
237
118
  </i:Interaction.Triggers>
238
-
239
119
  </Button>
240
-
241
120
  <Button
242
-
243
121
  MinWidth="80"
244
-
245
122
  Margin="5"
246
-
247
123
  Content="Cancel"
248
-
249
124
  IsCancel="True" />
250
-
251
125
  </StackPanel>
252
126
 
253
-
254
-
255
127
  <StackPanel>
256
-
257
128
  <HeaderedContentControl Margin="5" Header="Text1">
258
-
259
129
  <TextBox Text="{Binding Text1, UpdateSourceTrigger=PropertyChanged}" Validation.ErrorTemplate="{StaticResource ValidationTemplate}" />
260
-
261
130
  </HeaderedContentControl>
262
-
263
131
  <HeaderedContentControl Margin="5" Header="Text2">
264
-
265
132
  <TextBox Text="{Binding Text2, UpdateSourceTrigger=PropertyChanged}" Validation.ErrorTemplate="{StaticResource ValidationTemplate}" />
266
-
267
133
  </HeaderedContentControl>
268
-
269
134
  <HeaderedContentControl Margin="5" Header="Text3">
270
-
271
135
  <TextBox Text="{Binding Text3, UpdateSourceTrigger=PropertyChanged}" Validation.ErrorTemplate="{StaticResource ValidationTemplate}" />
272
-
273
136
  </HeaderedContentControl>
274
-
275
137
  </StackPanel>
276
-
277
138
  </DockPanel>
278
-
279
139
  </Window>
280
-
281
- ```
140
+ ```
282
-
283
-
284
-
141
+
285
- ```C#
142
+ ```cs
286
-
287
143
  using System;
288
-
289
144
  using System.Collections;
290
-
291
145
  using System.Collections.Generic;
292
-
293
146
  using System.ComponentModel;
294
-
295
147
  using System.ComponentModel.DataAnnotations;
296
-
297
148
  using System.Linq;
298
-
299
149
  using System.Runtime.CompilerServices;
300
-
301
150
  using Prism.Commands;
302
-
303
151
  using Prism.Mvvm;
304
152
 
305
-
306
-
307
153
  namespace WpfApp1
308
-
309
154
  {
310
-
311
155
  public class SubViewModel : BindableBase, INotifyDataErrorInfo
312
-
313
156
  {
314
-
315
157
  [Required(ErrorMessage = "何か入力してください。")]
316
-
317
158
  public string Text1 { get => _Text1; set => SetProperty(ref _Text1, value); }
318
-
319
159
  private string _Text1;
320
160
 
321
-
322
-
323
161
  [MinLength(10, ErrorMessage = "10文字以上入力してください。")]
324
-
325
162
  public string Text2 { get => _Text2; set => SetProperty(ref _Text2, value); }
326
-
327
163
  private string _Text2;
328
164
 
329
-
330
-
331
165
  [RegularExpression("[a-z]+", ErrorMessage = "a-zの文字列を入力してください。")]
332
-
333
166
  public string Text3 { get => _Text3; set => SetProperty(ref _Text3, value); }
334
-
335
167
  private string _Text3;
336
168
 
337
-
338
-
339
169
  public DelegateCommand DoSomethingCommand { get; }
340
170
 
341
171
 
342
-
343
-
344
-
345
172
  public SubViewModel()
346
-
347
173
  {
348
-
349
174
  errorsContainer = new ErrorsContainer<string>(x => ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(x)));
350
175
 
351
-
352
-
353
176
  Text1 = ""; // ""に深い意味はない。初期値nullから動かしてValidatorを通してるだけ
354
-
355
177
  Text2 = "";
356
-
357
178
  Text3 = "A";
358
179
 
359
-
360
-
361
180
  DoSomethingCommand = new DelegateCommand(
362
-
363
181
  () => System.Diagnostics.Debug.WriteLine("DoSomethigCommand"),
364
-
365
182
  () => !HasErrors)
366
-
367
183
  .ObservesProperty(() => HasErrors);
368
-
369
184
  }
370
185
 
371
186
 
372
-
373
-
374
-
375
187
  #region INotifyDataErrorInfo
376
-
377
188
  private readonly ErrorsContainer<string> errorsContainer;
378
-
379
189
  public bool HasErrors => errorsContainer.HasErrors;
380
-
381
190
  public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
382
-
383
191
  protected override bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
384
-
385
192
  {
386
-
387
193
  if(!base.SetProperty(ref storage, value, propertyName)) return false;
388
194
 
389
-
390
-
391
195
  var context = new ValidationContext(this) { MemberName = propertyName };
392
-
393
196
  var errors = new List<ValidationResult>();
394
-
395
197
  if(!Validator.TryValidateProperty(value, context, errors))
396
-
397
198
  {
398
-
399
199
  errorsContainer.SetErrors(propertyName, errors.Select(x => x.ErrorMessage));
400
-
401
200
  }
402
-
403
201
  else
404
-
405
202
  {
406
-
407
203
  errorsContainer.ClearErrors(propertyName);
408
-
409
204
  }
410
-
411
205
  RaisePropertyChanged(nameof(HasErrors));
412
-
413
206
  return true;
414
-
415
207
  }
416
-
417
208
  public IEnumerable GetErrors(string propertyName) => errorsContainer.GetErrors(propertyName);
418
-
419
209
  #endregion
420
-
421
210
  }
422
-
423
211
  }
424
-
425
- ```
212
+ ```