回答編集履歴

2

見直しキャンペーン中

2023/07/29 07:03

投稿

TN8001
TN8001

スコア9326

test CHANGED
@@ -1,297 +1,148 @@
1
1
  > ReactivePropertyを導入するとエラーチェックが簡単にできると調べて分かり導入しましたが、エラー状態を取得できずに困っています。
2
2
 
3
-
4
-
5
3
  現状`SetValidateNotifyError`や`SetValidateAttribute`していないので、なんの検証(バリデーション)もしていません。
6
-
7
4
  [MVVM をリアクティブプログラミングで快適に ReactiveProperty オーバービュー 2020 年版 前編 - Qiita](https://qiita.com/okazuki/items/7572f46848d0e93516b1#%E5%85%A5%E5%8A%9B%E5%80%A4%E3%81%AE%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3-slim-%E3%81%AB%E3%81%AF%E7%84%A1%E3%81%84%E6%A9%9F%E8%83%BD)
8
5
 
9
-
10
-
11
6
  例えば`double`にバインドしている`TextBox`にアルファベットを入力してエラーになるのは、バリデーション以前の話です(このあたりかなり悩ましいのですが^^;
12
-
13
7
  [C# - ReactivePropertyでTextBoxが空欄時にButtonをDisableにしたい。|teratail](https://teratail.com/questions/295331)
14
-
15
-
16
8
 
17
9
  > ReactivePropertyを使用しなくても、エラー状態を監視し、ボタンをOFFに出来る簡単な方法があるなら、それも知りたいです。
18
10
 
19
-
20
-
21
11
  要は`double`値以外の入力時にボタンを押せなくしたいということですかね?
22
-
23
12
  下記リンクで言及されている`Gu.Wpf.ValidationScope`が、楽そうでした(使い方があっているかあまり自信はないです^^;
24
-
25
13
  [Detecting WPF Validation Errors - Stack Overflow](https://stackoverflow.com/questions/127477/detecting-wpf-validation-errors)
26
-
27
-
28
-
29
14
  [NuGet Gallery | Gu.Wpf.ValidationScope 0.2.4](https://www.nuget.org/packages/Gu.Wpf.ValidationScope/0.2.4)
30
-
31
-
32
15
 
33
16
  もしバリデーション(例えばNumは0以上とか)も必要な場合は、組み合わせないほうがよさそうです(なんか動作がおかしくなる)
34
17
 
35
-
36
-
37
- ```xaml
18
+ ```xml
38
-
39
19
  <Window
40
-
41
20
  x:Class="Questions364210.Views.MainWindow"
42
-
43
21
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
44
-
45
22
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
46
-
47
23
  xmlns:v="clr-namespace:Questions364210.Views"
48
-
49
24
  xmlns:validation="https://github.com/JohanLarsson/Gu.Wpf.ValidationScope"
50
-
51
25
  xmlns:vm="clr-namespace:Questions364210.ViewModels"
52
-
53
26
  Width="525"
54
-
55
27
  Height="350">
56
28
 
57
-
58
-
59
29
  <Window.DataContext>
60
-
61
30
  <vm:MainWindowVM />
62
-
63
31
  </Window.DataContext>
64
32
 
65
-
66
-
67
33
  <Window.Resources>
68
-
69
34
  <Style x:Key="errorStyleGotFocus" TargetType="{x:Type TextBox}">
70
-
71
35
  <Style.Triggers>
72
-
73
36
  <Trigger Property="Validation.HasError" Value="True">
74
-
75
37
  <Setter Property="Background" Value="Red" />
76
-
77
38
  </Trigger>
78
-
79
39
  </Style.Triggers>
80
-
81
40
  </Style>
82
-
83
41
  </Window.Resources>
84
42
 
85
-
86
-
87
43
  <DockPanel>
88
-
89
44
  <Button
90
-
91
45
  HorizontalAlignment="Left"
92
-
93
46
  Command="{Binding UpdateCommand}"
94
-
95
47
  Content="データ更新"
96
-
97
48
  DockPanel.Dock="Bottom"
98
-
99
49
  IsEnabled="{Binding (validation:Scope.HasError), Converter={v:InverseBooleanConverter}, ElementName=Form}" />
100
50
 
101
-
102
-
103
51
  <TabControl x:Name="Form" validation:Scope.ForInputTypes="{x:Static validation:InputTypeCollection.Default}">
104
-
105
52
  <TabItem Header="顧客">
106
-
107
53
  <DataGrid
108
-
109
54
  AutoGenerateColumns="False"
110
-
111
55
  CanUserAddRows="False"
112
-
113
56
  ItemsSource="{Binding ClientData}">
114
-
115
57
  <DataGrid.Columns>
116
-
117
58
  <DataGridTextColumn
118
-
119
59
  Binding="{Binding ID}"
120
-
121
60
  Header="ID"
122
-
123
61
  IsReadOnly="True" />
124
-
125
62
  <DataGridTextColumn
126
-
127
63
  Binding="{Binding Name}"
128
-
129
64
  Header="名前"
130
-
131
65
  IsReadOnly="True" />
132
-
133
66
  <DataGridTextColumn
134
-
135
67
  Binding="{Binding Num}"
136
-
137
68
  EditingElementStyle="{StaticResource errorStyleGotFocus}"
138
-
139
69
  Header="対象No" />
140
-
141
70
  <DataGridTextColumn
142
-
143
71
  Binding="{Binding Other}"
144
-
145
72
  Header="備考"
146
-
147
73
  IsReadOnly="True" />
148
-
149
74
  </DataGrid.Columns>
150
-
151
75
  </DataGrid>
152
-
153
76
  </TabItem>
154
-
155
77
  </TabControl>
156
-
157
78
  </DockPanel>
158
-
159
79
  </Window>
160
-
161
80
  ```
162
81
 
163
-
164
-
165
- ```C#
82
+ ```cs
166
-
167
83
  using Livet;
168
-
169
84
  using Livet.Commands;
170
-
171
85
  using System.Collections.ObjectModel;
172
-
173
86
  using System.Diagnostics;
174
87
 
175
-
176
-
177
88
  namespace Questions364210.ViewModels
178
-
179
89
  {
180
-
181
90
  class MainWindowVM : ViewModel
182
-
183
91
  {
184
-
185
92
  public ObservableCollection<ClientInfo> ClientData { get; }
186
-
187
93
  public ViewModelCommand UpdateCommand { get; }
188
94
 
189
-
190
-
191
95
  public MainWindowVM()
192
-
193
96
  {
194
-
195
97
  ClientData = new ObservableCollection<ClientInfo>
196
-
197
98
  {
198
-
199
99
  new ClientInfo { ID = 1, Name = "クライアント1", Num = 1.1, Other = "" },
200
-
201
100
  new ClientInfo { ID = 50, Name = "クライアント2", Num = 1.1, Other = "" },
202
-
203
101
  new ClientInfo { ID = 100, Name = "クライアント3", Num = 1.1, Other = "" },
204
-
205
102
  new ClientInfo { ID = 999, Name = "クライアント4", Num = 1.1, Other = "" },
206
-
207
103
  };
208
104
 
209
-
210
-
211
105
  UpdateCommand = new ViewModelCommand(Update);
212
-
213
106
  }
214
107
 
215
-
216
-
217
108
  private void Update()
218
-
219
109
  {
220
-
221
110
  foreach (var i in ClientData)
222
-
223
111
  {
224
-
225
112
  Debug.WriteLine($"ID: {i.ID}, Name: {i.Name}, Num: {i.Num}, Other: {i.Other}");
226
-
227
113
  }
228
-
229
114
  }
230
-
231
115
  }
232
116
 
233
-
234
-
235
117
  class ClientInfo : ViewModel
236
-
237
118
  {
238
-
239
119
  public int ID { get; set; }
240
-
241
120
  public string Name { get; set; }
242
121
 
243
-
244
-
245
122
  private double _Num;
246
-
247
123
  public double Num { get => _Num; set => RaisePropertyChangedIfSet(ref _Num, value); }
248
124
 
249
-
250
-
251
125
  public string Other { get; set; }
252
-
253
126
  }
254
-
255
127
  }
256
-
257
128
  ```
258
129
 
259
-
260
-
261
- ```C#
130
+ ```cs
262
-
263
131
  using System;
264
-
265
132
  using System.Globalization;
266
-
267
133
  using System.Windows;
268
-
269
134
  using System.Windows.Data;
270
-
271
135
  using System.Windows.Markup;
272
136
 
273
-
274
-
275
137
  namespace Questions364210.Views
276
-
277
138
  {
278
-
279
139
  public class InverseBooleanConverter : MarkupExtension, IValueConverter
280
-
281
140
  {
282
-
283
141
  public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
284
-
285
142
  => !(bool)value;
286
-
287
143
  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
288
-
289
144
  => throw new NotImplementedException();
290
-
291
145
  public override object ProvideValue(IServiceProvider serviceProvider) => this;
292
-
293
146
  }
294
-
295
147
  }
296
-
297
148
  ```

1

MainWindowクラスを載せる必要もない

2021/10/14 09:03

投稿

TN8001
TN8001

スコア9326

test CHANGED
@@ -292,16 +292,6 @@
292
292
 
293
293
  }
294
294
 
295
-
296
-
297
- public partial class MainWindow : Window
298
-
299
- {
300
-
301
- public MainWindow() => InitializeComponent();
302
-
303
- }
304
-
305
295
  }
306
296
 
307
297
  ```