teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

見直しキャンペーン中

2023/07/29 08:03

投稿

TN8001
TN8001

スコア10114

answer CHANGED
@@ -1,184 +1,184 @@
1
- > メインウィンドウのリストボックスアイテムをダブルクリックすると、テキストブロックにバインディングしてる値を取得してサブウィンドウに表示したいです。
2
-
3
- データバインディングを勉強されたのですね。前回よりだいぶ進んでいるようですね^^
4
-
5
- > ダブルクリックしたアイテムをToStringメソッドでstr変数に入れてサブウィンドウに入れようと思った
6
-
7
- 何をバインディングしているかが不明ですが、`listBox.SelectedItem`自体は個々のアイテム(`check`や`textArray`プロパティがあるクラス)になっています。
8
- しかし`SelectedItem`は`object`のためキャストが必要です。
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)
10
-
11
- 例えばこのような
12
- ```C#
13
- var item = listBox.SelectedItem as ToDoItem;
14
- var str = item?.Text;
15
- ```
16
-
17
- ---
18
-
19
- しかし`ListBox`自体の`MouseDoubleClick`ですと、何もない部分も反応してしまってあまり使い勝手がよくないです。
20
- `ListBoxItem`に`MouseDoubleClick`を付けるほうがおすすめです。
21
-
22
- サブウィンドウに表示するときもせっかくなのでバインディングしましょう。
23
-
24
- 表示と言っていますが、実際は編集でしょうか?
25
- 表示だけならいらないのですが、編集するとなると`INotifyPropertyChanged`を実装する必要があります(WPFでは最重要インターフェースです)
26
-
27
- 回答では↓を使用しました。
28
- [NuGet Gallery | CommunityToolkit.Mvvm 7.0.3](https://www.nuget.org/packages/CommunityToolkit.Mvvm/7.0.3)
29
- [ObservableObject - Windows Community Toolkit | Microsoft Docs](https://docs.microsoft.com/ja-jp/windows/communitytoolkit/mvvm/observableobject)
30
-
31
-
32
- MainWindow
33
- ```xaml
34
- <Window
35
- x:Class="Questions368346.MainWindow"
36
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
37
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
38
- Title="MainWindow"
39
- Width="800"
40
- Height="450">
41
- <Grid>
42
- <Grid.RowDefinitions>
43
- <RowDefinition Height="Auto" />
44
- <RowDefinition />
45
- </Grid.RowDefinitions>
46
- <!-- 編集 こうしないのであればIsSynchronizedWithCurrentItemは不要 -->
47
- <TextBox Margin="5" Text="{Binding /Text, UpdateSourceTrigger=PropertyChanged}" />
48
-
49
- <ListBox
50
- x:Name="listBox"
51
- Grid.Row="1"
52
- Margin="5"
53
- Background="WhiteSmoke"
54
- IsSynchronizedWithCurrentItem="True"
55
- ItemsSource="{Binding}"
56
- SelectionMode="Single">
57
- <ListBox.ItemContainerStyle>
58
- <Style TargetType="ListBoxItem">
59
- <EventSetter Event="MouseDoubleClick" Handler="ListBoxItem_MouseDoubleClick" />
60
- </Style>
61
- </ListBox.ItemContainerStyle>
62
- <ListBox.ItemTemplate>
63
- <DataTemplate>
64
- <StackPanel Orientation="Horizontal">
65
- <CheckBox VerticalContentAlignment="Center" IsChecked="{Binding Check}" />
66
- <TextBlock Text="{Binding Text}" />
67
- </StackPanel>
68
- </DataTemplate>
69
- </ListBox.ItemTemplate>
70
- </ListBox>
71
- </Grid>
72
- </Window>
73
- ```
74
-
75
- ```C#
76
- using System.Collections.ObjectModel;
77
- using System.Windows;
78
- using System.Windows.Controls;
79
- using System.Windows.Input;
80
- using CommunityToolkit.Mvvm.ComponentModel;
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;
88
-
89
- public bool Check { get => _Check; set => SetProperty(ref _Check, value); }
90
- private bool _Check;
91
- }
92
-
93
- public partial class MainWindow : Window
94
- {
95
- public MainWindow()
96
- {
97
- InitializeComponent();
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
- ```xaml
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
- ```C#
164
- using System.Windows;
165
-
166
- namespace Questions368346
167
- {
168
- public partial class Window1 : Window
169
- {
170
- public Window1() => InitializeComponent();
171
-
172
- private void OkButton_Click(object sender, RoutedEventArgs e)
173
- => DialogResult = true;
174
- }
175
- }
176
- ```
177
-
178
- ---
179
-
180
- 個人的にはダイアログをポンポン出すのは趣味でないので、編集なら同じウィンドウ内でやりたいですね。
181
- 編集だけなら非常に簡単にできます。
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)
183
-
1
+ > メインウィンドウのリストボックスアイテムをダブルクリックすると、テキストブロックにバインディングしてる値を取得してサブウィンドウに表示したいです。
2
+
3
+ データバインディングを勉強されたのですね。前回よりだいぶ進んでいるようですね^^
4
+
5
+ > ダブルクリックしたアイテムをToStringメソッドでstr変数に入れてサブウィンドウに入れようと思った
6
+
7
+ 何をバインディングしているかが不明ですが、`listBox.SelectedItem`自体は個々のアイテム(`check`や`textArray`プロパティがあるクラス)になっています。
8
+ しかし`SelectedItem`は`object`のためキャストが必要です。
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)
10
+
11
+ 例えばこのような
12
+ ```cs
13
+ var item = listBox.SelectedItem as ToDoItem;
14
+ var str = item?.Text;
15
+ ```
16
+
17
+ ---
18
+
19
+ しかし`ListBox`自体の`MouseDoubleClick`ですと、何もない部分も反応してしまってあまり使い勝手がよくないです。
20
+ `ListBoxItem`に`MouseDoubleClick`を付けるほうがおすすめです。
21
+
22
+ サブウィンドウに表示するときもせっかくなのでバインディングしましょう。
23
+
24
+ 表示と言っていますが、実際は編集でしょうか?
25
+ 表示だけならいらないのですが、編集するとなると`INotifyPropertyChanged`を実装する必要があります(WPFでは最重要インターフェースです)
26
+
27
+ 回答では↓を使用しました。
28
+ [NuGet Gallery | CommunityToolkit.Mvvm 7.0.3](https://www.nuget.org/packages/CommunityToolkit.Mvvm/7.0.3)
29
+ [ObservableObject - Windows Community Toolkit | Microsoft Docs](https://docs.microsoft.com/ja-jp/windows/communitytoolkit/mvvm/observableobject)
30
+
31
+
32
+ MainWindow
33
+ ```xml
34
+ <Window
35
+ x:Class="Questions368346.MainWindow"
36
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
37
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
38
+ Title="MainWindow"
39
+ Width="800"
40
+ Height="450">
41
+ <Grid>
42
+ <Grid.RowDefinitions>
43
+ <RowDefinition Height="Auto" />
44
+ <RowDefinition />
45
+ </Grid.RowDefinitions>
46
+ <!-- 編集 こうしないのであればIsSynchronizedWithCurrentItemは不要 -->
47
+ <TextBox Margin="5" Text="{Binding /Text, UpdateSourceTrigger=PropertyChanged}" />
48
+
49
+ <ListBox
50
+ x:Name="listBox"
51
+ Grid.Row="1"
52
+ Margin="5"
53
+ Background="WhiteSmoke"
54
+ IsSynchronizedWithCurrentItem="True"
55
+ ItemsSource="{Binding}"
56
+ SelectionMode="Single">
57
+ <ListBox.ItemContainerStyle>
58
+ <Style TargetType="ListBoxItem">
59
+ <EventSetter Event="MouseDoubleClick" Handler="ListBoxItem_MouseDoubleClick" />
60
+ </Style>
61
+ </ListBox.ItemContainerStyle>
62
+ <ListBox.ItemTemplate>
63
+ <DataTemplate>
64
+ <StackPanel Orientation="Horizontal">
65
+ <CheckBox VerticalContentAlignment="Center" IsChecked="{Binding Check}" />
66
+ <TextBlock Text="{Binding Text}" />
67
+ </StackPanel>
68
+ </DataTemplate>
69
+ </ListBox.ItemTemplate>
70
+ </ListBox>
71
+ </Grid>
72
+ </Window>
73
+ ```
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;
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;
88
+
89
+ public bool Check { get => _Check; set => SetProperty(ref _Check, value); }
90
+ private bool _Check;
91
+ }
92
+
93
+ public partial class MainWindow : Window
94
+ {
95
+ public MainWindow()
96
+ {
97
+ InitializeComponent();
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
164
+ using System.Windows;
165
+
166
+ namespace Questions368346
167
+ {
168
+ public partial class Window1 : Window
169
+ {
170
+ public Window1() => InitializeComponent();
171
+
172
+ private void OkButton_Click(object sender, RoutedEventArgs e)
173
+ => DialogResult = true;
174
+ }
175
+ }
176
+ ```
177
+
178
+ ---
179
+
180
+ 個人的にはダイアログをポンポン出すのは趣味でないので、編集なら同じウィンドウ内でやりたいですね。
181
+ 編集だけなら非常に簡単にできます。
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)
183
+
184
184
  とはいえ追加が絡むとなると、また話が変わってくるのですが^^;