回答編集履歴

1

見直しキャンペーン中

2023/07/29 08:03

投稿

TN8001
TN8001

スコア9341

test CHANGED
@@ -1,367 +1,184 @@
1
1
  > メインウィンドウのリストボックスアイテムをダブルクリックすると、テキストブロックにバインディングしてる値を取得してサブウィンドウに表示したいです。
2
-
3
-
4
2
 
5
3
  データバインディングを勉強されたのですね。前回よりだいぶ進んでいるようですね^^
6
4
 
7
-
8
-
9
5
  > ダブルクリックしたアイテムをToStringメソッドでstr変数に入れてサブウィンドウに入れようと思った
10
6
 
11
-
12
-
13
7
  何をバインディングしているかが不明ですが、`listBox.SelectedItem`自体は個々のアイテム(`check`や`textArray`プロパティがあるクラス)になっています。
14
-
15
8
  しかし`SelectedItem`は`object`のためキャストが必要です。
16
-
17
9
  [Selector.SelectedItem プロパティ (System.Windows.Controls.Primitives) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.controls.primitives.selector.selecteditem?view=net-5.0)
18
10
 
19
-
20
-
21
11
  例えばこのような
22
-
23
- ```C#
12
+ ```cs
24
-
25
13
  var item = listBox.SelectedItem as ToDoItem;
26
-
27
14
  var str = item?.Text;
28
-
29
15
  ```
30
-
31
-
32
16
 
33
17
  ---
34
18
 
35
-
36
-
37
19
  しかし`ListBox`自体の`MouseDoubleClick`ですと、何もない部分も反応してしまってあまり使い勝手がよくないです。
38
-
39
20
  `ListBoxItem`に`MouseDoubleClick`を付けるほうがおすすめです。
40
-
41
-
42
21
 
43
22
  サブウィンドウに表示するときもせっかくなのでバインディングしましょう。
44
23
 
45
-
46
-
47
24
  表示と言っていますが、実際は編集でしょうか?
48
-
49
25
  表示だけならいらないのですが、編集するとなると`INotifyPropertyChanged`を実装する必要があります(WPFでは最重要インターフェースです)
50
26
 
51
-
52
-
53
27
  回答では↓を使用しました。
54
-
55
28
  [NuGet Gallery | CommunityToolkit.Mvvm 7.0.3](https://www.nuget.org/packages/CommunityToolkit.Mvvm/7.0.3)
56
-
57
29
  [ObservableObject - Windows Community Toolkit | Microsoft Docs](https://docs.microsoft.com/ja-jp/windows/communitytoolkit/mvvm/observableobject)
58
30
 
59
31
 
60
-
61
-
62
-
63
32
  MainWindow
64
-
65
- ```xaml
33
+ ```xml
66
-
67
34
  <Window
68
-
69
35
  x:Class="Questions368346.MainWindow"
70
-
71
36
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
72
-
73
37
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
74
-
75
38
  Title="MainWindow"
76
-
77
39
  Width="800"
78
-
79
40
  Height="450">
80
-
81
41
  <Grid>
82
-
83
42
  <Grid.RowDefinitions>
84
-
85
43
  <RowDefinition Height="Auto" />
86
-
87
44
  <RowDefinition />
88
-
89
45
  </Grid.RowDefinitions>
90
-
91
46
  <!-- 編集 こうしないのであればIsSynchronizedWithCurrentItemは不要 -->
92
-
93
47
  <TextBox Margin="5" Text="{Binding /Text, UpdateSourceTrigger=PropertyChanged}" />
94
48
 
95
-
96
-
97
49
  <ListBox
98
-
99
50
  x:Name="listBox"
100
-
101
51
  Grid.Row="1"
102
-
103
52
  Margin="5"
104
-
105
53
  Background="WhiteSmoke"
106
-
107
54
  IsSynchronizedWithCurrentItem="True"
108
-
109
55
  ItemsSource="{Binding}"
110
-
111
56
  SelectionMode="Single">
112
-
113
57
  <ListBox.ItemContainerStyle>
114
-
115
58
  <Style TargetType="ListBoxItem">
116
-
117
59
  <EventSetter Event="MouseDoubleClick" Handler="ListBoxItem_MouseDoubleClick" />
118
-
119
60
  </Style>
120
-
121
61
  </ListBox.ItemContainerStyle>
122
-
123
62
  <ListBox.ItemTemplate>
124
-
125
63
  <DataTemplate>
126
-
127
64
  <StackPanel Orientation="Horizontal">
128
-
129
65
  <CheckBox VerticalContentAlignment="Center" IsChecked="{Binding Check}" />
130
-
131
66
  <TextBlock Text="{Binding Text}" />
132
-
133
67
  </StackPanel>
134
-
135
68
  </DataTemplate>
136
-
137
69
  </ListBox.ItemTemplate>
138
-
139
70
  </ListBox>
140
-
141
71
  </Grid>
142
-
143
72
  </Window>
144
-
145
73
  ```
146
74
 
75
+ ```cs
76
+ using System.Collections.ObjectModel;
77
+ using System.Windows;
78
+ using System.Windows.Controls;
79
+ using System.Windows.Input;
80
+ using CommunityToolkit.Mvvm.ComponentModel;
147
81
 
82
+ namespace Questions368346
83
+ {
84
+ class ToDoItem : ObservableObject
85
+ {
86
+ public string Text { get => _Text; set => SetProperty(ref _Text, value); }
87
+ private string _Text;
148
88
 
89
+ public bool Check { get => _Check; set => SetProperty(ref _Check, value); }
149
- ```C#
90
+ private bool _Check;
91
+ }
150
92
 
151
- using System.Collections.ObjectModel;
93
+ public partial class MainWindow : Window
94
+ {
95
+ public MainWindow()
96
+ {
97
+ InitializeComponent();
152
98
 
99
+ DataContext = new ObservableCollection<ToDoItem>
100
+ {
101
+ new ToDoItem { Text = "aaa", },
102
+ new ToDoItem { Text = "bbb", },
103
+ new ToDoItem { Text = "ccc", },
104
+ };
105
+ }
106
+
107
+ private void ListBoxItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
108
+ {
109
+ if (sender is ListBoxItem listBoxItem)
110
+ {
111
+ if (listBoxItem.DataContext is ToDoItem item)
112
+ {
113
+ var win1 = new Window1
114
+ {
115
+ Owner = this,
116
+ // DataContextの個々のアイテムをセット
117
+ // Window1でも <TextBox Text="{Binding Text}" /> のようにバインディングできる
118
+ DataContext = item,
119
+ };
120
+
121
+ win1.addButton.Visibility = Visibility.Collapsed;
122
+ win1.canButton.Visibility = Visibility.Collapsed;
123
+ win1.okButton.Visibility = Visibility.Visible;
124
+
125
+ // その場で書き換えてしまうので、もし編集のキャンセルが必要な場合はひと工夫必要
126
+ win1.ShowDialog();
127
+ }
128
+ }
129
+ }
130
+ }
131
+ }
132
+ ```
133
+
134
+ SubWindow
135
+ ```xml
136
+ <Window
137
+ x:Class="Questions368346.Window1"
138
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
139
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
140
+ Title="SubWindow"
141
+ Width="400"
142
+ FocusManager.FocusedElement="{Binding ElementName=mainText}"
143
+ SizeToContent="Height"
144
+ WindowStartupLocation="CenterOwner">
145
+ <StackPanel Margin="5">
146
+ <TextBox x:Name="mainText" Margin="5,0" Text="{Binding Text}" />
147
+
148
+ <StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
149
+ <StackPanel.Resources>
150
+ <Style TargetType="Button">
151
+ <Setter Property="MinWidth" Value="80" />
152
+ <Setter Property="Margin" Value="5" />
153
+ </Style>
154
+ </StackPanel.Resources>
155
+ <Button x:Name="addButton" Content="追加" />
156
+ <Button x:Name="okButton" Content="OK" IsDefault="True" Click="OkButton_Click" />
157
+ <Button x:Name="canButton" Content="キャンセル" IsCancel="True" />
158
+ </StackPanel>
159
+ </StackPanel>
160
+ </Window>
161
+ ```
162
+
163
+ ```cs
153
164
  using System.Windows;
154
165
 
155
- using System.Windows.Controls;
156
-
157
- using System.Windows.Input;
158
-
159
- using CommunityToolkit.Mvvm.ComponentModel;
160
-
161
-
162
-
163
166
  namespace Questions368346
164
-
165
167
  {
166
-
167
- class ToDoItem : ObservableObject
168
+ public partial class Window1 : Window
168
-
169
169
  {
170
-
171
- public string Text { get => _Text; set => SetProperty(ref _Text, value); }
172
-
173
- private string _Text;
174
-
175
-
176
-
177
- public bool Check { get => _Check; set => SetProperty(ref _Check, value); }
178
-
179
- private bool _Check;
180
-
181
- }
182
-
183
-
184
-
185
- public partial class MainWindow : Window
186
-
187
- {
188
-
189
- public MainWindow()
190
-
191
- {
192
-
193
- InitializeComponent();
194
-
195
-
196
-
197
- DataContext = new ObservableCollection<ToDoItem>
198
-
199
- {
200
-
201
- new ToDoItem { Text = "aaa", },
202
-
203
- new ToDoItem { Text = "bbb", },
204
-
205
- new ToDoItem { Text = "ccc", },
206
-
207
- };
208
-
209
- }
210
-
211
-
212
-
213
- private void ListBoxItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
214
-
215
- {
216
-
217
- if (sender is ListBoxItem listBoxItem)
218
-
219
- {
220
-
221
- if (listBoxItem.DataContext is ToDoItem item)
222
-
223
- {
224
-
225
- var win1 = new Window1
226
-
227
- {
228
-
229
- Owner = this,
230
-
231
- // DataContextの個々のアイテムをセット
232
-
233
- // Window1でも <TextBox Text="{Binding Text}" /> のようにバインディングできる
234
-
235
- DataContext = item,
236
-
237
- };
238
-
239
-
240
-
241
- win1.addButton.Visibility = Visibility.Collapsed;
242
-
243
- win1.canButton.Visibility = Visibility.Collapsed;
244
-
245
- win1.okButton.Visibility = Visibility.Visible;
246
-
247
-
248
-
249
- // その場で書き換えてしまうので、もし編集のキャンセルが必要な場合はひと工夫必要
250
-
251
- win1.ShowDialog();
252
-
253
- }
254
-
255
- }
256
-
257
- }
258
-
259
- }
260
-
261
- }
262
-
263
- ```
264
-
265
-
266
-
267
- SubWindow
268
-
269
- ```xaml
270
-
271
- <Window
272
-
273
- x:Class="Questions368346.Window1"
274
-
275
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
276
-
277
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
278
-
279
- Title="SubWindow"
280
-
281
- Width="400"
282
-
283
- FocusManager.FocusedElement="{Binding ElementName=mainText}"
284
-
285
- SizeToContent="Height"
286
-
287
- WindowStartupLocation="CenterOwner">
288
-
289
- <StackPanel Margin="5">
290
-
291
- <TextBox x:Name="mainText" Margin="5,0" Text="{Binding Text}" />
292
-
293
-
294
-
295
- <StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
296
-
297
- <StackPanel.Resources>
298
-
299
- <Style TargetType="Button">
300
-
301
- <Setter Property="MinWidth" Value="80" />
302
-
303
- <Setter Property="Margin" Value="5" />
304
-
305
- </Style>
306
-
307
- </StackPanel.Resources>
308
-
309
- <Button x:Name="addButton" Content="追加" />
310
-
311
- <Button x:Name="okButton" Content="OK" IsDefault="True" Click="OkButton_Click" />
312
-
313
- <Button x:Name="canButton" Content="キャンセル" IsCancel="True" />
314
-
315
- </StackPanel>
316
-
317
- </StackPanel>
318
-
319
- </Window>
320
-
321
- ```
322
-
323
-
324
-
325
- ```C#
326
-
327
- using System.Windows;
328
-
329
-
330
-
331
- namespace Questions368346
332
-
333
- {
334
-
335
- public partial class Window1 : Window
336
-
337
- {
338
-
339
170
  public Window1() => InitializeComponent();
340
171
 
341
-
342
-
343
172
  private void OkButton_Click(object sender, RoutedEventArgs e)
344
-
345
173
  => DialogResult = true;
346
-
347
174
  }
348
-
349
175
  }
350
-
351
176
  ```
352
-
353
-
354
177
 
355
178
  ---
356
179
 
357
-
358
-
359
180
  個人的にはダイアログをポンポン出すのは趣味でないので、編集なら同じウィンドウ内でやりたいですね。
360
-
361
181
  編集だけなら非常に簡単にできます。
362
-
363
182
  [マスターと詳細のバインディング シナリオ - WPF .NET | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/desktop/wpf/data/?view=netdesktop-5.0&redirectedfrom=MSDN#master-detail-binding-scenario)
364
183
 
365
-
366
-
367
184
  とはいえ追加が絡むとなると、また話が変わってくるのですが^^;