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

回答編集履歴

1

見直しキャンペーン中

2023/07/23 04:03

投稿

TN8001
TN8001

スコア10114

answer CHANGED
@@ -1,230 +1,230 @@
1
- 単独選択か複数選択かで変わってきます。
2
- 見てもらったほうが早いので、それぞれ向き用の2つの表示法を用意しました。
3
- `SelectionMode`をコンボボックスで切り替えられるようになっています。違いを確認してください。
4
-
5
- ```xaml
6
- <Window
7
- x:Class="Questions284783.Views.MainWindow"
8
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
9
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
10
- xmlns:controls="clr-namespace:System.Windows.Controls;assembly=PresentationFramework"
11
- xmlns:prism="http://prismlibrary.com/"
12
- xmlns:sys="clr-namespace:System;assembly=mscorlib"
13
- Width="525"
14
- Height="350"
15
- prism:ViewModelLocator.AutoWireViewModel="True">
16
-
17
- <!-- prism:ViewModelLocator.AutoWireViewModel="True" があるからいらないはず -->
18
- <!--<Window.DataContext>
19
- <l:MainWindowViewModel />
20
- </Window.DataContext>-->
21
-
22
- <Window.Resources>
23
- <!-- SelectionMode選択用データ(本題には無関係 違いを確認しやすいように) -->
24
- <ObjectDataProvider
25
- x:Key="selectionMode"
26
- MethodName="GetValues"
27
- ObjectType="{x:Type sys:Enum}">
28
- <ObjectDataProvider.MethodParameters>
29
- <x:Type TypeName="controls:SelectionMode" />
30
- </ObjectDataProvider.MethodParameters>
31
- </ObjectDataProvider>
32
- </Window.Resources>
33
-
34
- <Grid>
35
- <Grid.ColumnDefinitions>
36
- <ColumnDefinition />
37
- <ColumnDefinition Width="2*" />
38
- </Grid.ColumnDefinitions>
39
- <Grid.RowDefinitions>
40
- <RowDefinition Height="Auto" />
41
- <RowDefinition />
42
- </Grid.RowDefinitions>
43
-
44
- <Grid>
45
- <Grid.ColumnDefinitions>
46
- <ColumnDefinition Width="Auto" />
47
- <ColumnDefinition />
48
- </Grid.ColumnDefinitions>
49
- <Label
50
- Margin="5"
51
- VerticalAlignment="Center"
52
- Content="表題" />
53
- <TextBox
54
- Grid.Column="1"
55
- Margin="5"
56
- VerticalAlignment="Center"
57
- Text="{Binding Txt_Title, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
58
- TextWrapping="Wrap" />
59
- </Grid>
60
-
61
- <Grid Grid.Column="1">
62
- <Grid.ColumnDefinitions>
63
- <ColumnDefinition Width="Auto" />
64
- <ColumnDefinition />
65
- <ColumnDefinition Width="Auto" />
66
- </Grid.ColumnDefinitions>
67
- <Label
68
- Margin="5"
69
- VerticalAlignment="Center"
70
- Content="Memo" />
71
- <TextBox
72
- Grid.Column="1"
73
- Margin="5"
74
- VerticalAlignment="Center"
75
- Text="{Binding Txt_Memo, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
76
- TextWrapping="Wrap" />
77
- <Button
78
- Grid.Column="2"
79
- MinWidth="56"
80
- Margin="5"
81
- Command="{Binding ExecuteCommand}"
82
- Content="追加" />
83
- </Grid>
84
-
85
- <Grid Grid.Row="1">
86
- <Grid.RowDefinitions>
87
- <RowDefinition Height="Auto" />
88
- <RowDefinition />
89
- </Grid.RowDefinitions>
90
-
91
- <!-- SelectionMode選択 -->
92
- <ComboBox
93
- x:Name="comboBox"
94
- Margin="5"
95
- ItemsSource="{Binding Source={StaticResource selectionMode}}"
96
- SelectedIndex="0" />
97
- <ListBox
98
- x:Name="lst_Title"
99
- Grid.Row="1"
100
- Margin="5"
101
- DisplayMemberPath="Title"
102
- IsSynchronizedWithCurrentItem="True"
103
- ItemsSource="{Binding TaskList}"
104
- SelectionMode="{Binding SelectedValue, ElementName=comboBox}" />
105
- </Grid>
106
-
107
- <Grid Grid.Row="1" Grid.Column="1">
108
- <Grid.RowDefinitions>
109
- <RowDefinition />
110
- <RowDefinition Height="Auto" />
111
- </Grid.RowDefinitions>
112
-
113
- <!-- SelectedItems をもらう -->
114
- <ListBox Margin="5" ItemsSource="{Binding SelectedItems, ElementName=lst_Title}">
115
- <ListBox.ItemTemplate>
116
- <DataTemplate>
117
- <StackPanel>
118
- <TextBlock FontWeight="Bold" Text="{Binding Title}" />
119
- <TextBlock Text="{Binding Detail}" />
120
- </StackPanel>
121
- </DataTemplate>
122
- </ListBox.ItemTemplate>
123
- </ListBox>
124
-
125
- <!-- lst_Title が SelectionMode="Single" ならこれもあり -->
126
- <StackPanel Grid.Row="1">
127
- <TextBlock
128
- Margin="5"
129
- FontWeight="Bold"
130
- Text="{Binding TaskList/Title}" />
131
- <TextBlock Margin="5" Text="{Binding TaskList/Detail}" />
132
- </StackPanel>
133
- </Grid>
134
- </Grid>
135
- </Window>
136
- ```
137
-
138
- ```C#
139
- using System.Collections.ObjectModel;
140
- using Prism.Commands;
141
- using Prism.Mvvm;
142
-
143
- namespace Questions284783.ViewModels
144
- {
145
- public class MainWindowViewModel : BindableBase
146
- {
147
- private string txt_Title;
148
- public string Txt_Title
149
- {
150
- get => txt_Title;
151
- set
152
- {
153
- if(SetProperty(ref txt_Title, value))
154
- ExecuteCommand.RaiseCanExecuteChanged();
155
- }
156
- }
157
-
158
- private string txt_Memo;
159
- public string Txt_Memo
160
- {
161
- get => txt_Memo;
162
- set
163
- {
164
- if(SetProperty(ref txt_Memo, value))
165
- ExecuteCommand.RaiseCanExecuteChanged();
166
- }
167
- }
168
-
169
- public ObservableCollection<Task> TaskList { get; } = new ObservableCollection<Task>();
170
-
171
- public DelegateCommand ExecuteCommand { get; private set; }
172
-
173
- public MainWindowViewModel()
174
- {
175
- // 検証時面倒なので先入れ^^;
176
- TaskList.Add(new Task { Title = "aaa", Detail = "111" });
177
- TaskList.Add(new Task { Title = "bbb", Detail = "222" });
178
- TaskList.Add(new Task { Title = "ccc", Detail = "333" });
179
-
180
- ExecuteCommand = new DelegateCommand(Execute, CanExecute);
181
- }
182
-
183
- private void Execute()
184
- {
185
- TaskList.Add(new Task { Title = Txt_Title, Detail = Txt_Memo });
186
-
187
- Txt_Title = "";
188
- Txt_Memo = "";
189
-
190
- ExecuteCommand.RaiseCanExecuteChanged();
191
- }
192
-
193
- private bool CanExecute() => !string.IsNullOrEmpty(Txt_Title);
194
- }
195
-
196
- public class Task
197
- {
198
- public string Title { get; set; }
199
- public string Detail { get; set; }
200
- }
201
- }
202
- ```
203
-
204
-
205
- バインディング中のスラッシュ`{Binding TaskList/Title}`については↓あたりを参照してください(説明放棄^^;
206
- [方法: 階層データでマスター詳細パターンを使用する - WPF | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/framework/wpf/data/how-to-use-the-master-detail-pattern-with-hierarchical-data)
207
- [WPF4.5入門 その56「コレクションのバインディング」 - かずきのBlog@hatena](https://blog.okazuki.jp/entry/2014/10/29/220236) 最後のほうの「現在の選択項目をバインディングする方法」
208
-
209
- ---
210
-
211
- ここまでは`View`だけでの対応ですが、選択されているというのが重要な情報の場合(ファイルに選択情報も保存して次回復元する等)は、別の手のほうがいいかもしれません。
212
-
213
- `Task`クラスに`bool IsSelected`プロパティを用意して、`lst_Title`では`ListBoxItem`の`IsSelected`にバインドし、`lst_Detail`では`ListBoxItem`の`Visibility`にバインドします。
214
- どちらの`ListBox`も`TaskList`がソースですが、`lst_Detail`では未選択のものは無いように見えます。
215
- ちょっとずるいようですが、割とポピュラーな手段だと思います。もし気になるようでしたら追記しますので言ってください。
216
-
217
- ---
218
-
219
- > ソースコードに改善点ありましたらご指摘願います。
220
-
221
- `prism:ViewModelLocator.AutoWireViewModel="True"`があるので`<l:MainWindowViewModel />`で入れる必要はないはずです。
222
-
223
- ぐちゃぐちゃ`Margin`(`Margin="66,5,122,5"`のようなもの)はよろしくないです(`Margin="5"`や`Margin="5,2"`のようなすっきりしたものならOKです)
224
- ユーザーのフォント設定やウィンドウのリサイズ等で、文字が見切れたりレイアウト崩れの原因になります。
225
- はっきり言って面倒なのですが、入れ子`Grid`等で地道にレイアウトしてください。
226
-
227
- `Width="56"`もフォントによっては見切れるので、`MinWidth="56"`にしておくと安心です。
228
-
229
- C#コードは特にないです^^
1
+ 単独選択か複数選択かで変わってきます。
2
+ 見てもらったほうが早いので、それぞれ向き用の2つの表示法を用意しました。
3
+ `SelectionMode`をコンボボックスで切り替えられるようになっています。違いを確認してください。
4
+
5
+ ```xml
6
+ <Window
7
+ x:Class="Questions284783.Views.MainWindow"
8
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
9
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
10
+ xmlns:controls="clr-namespace:System.Windows.Controls;assembly=PresentationFramework"
11
+ xmlns:prism="http://prismlibrary.com/"
12
+ xmlns:sys="clr-namespace:System;assembly=mscorlib"
13
+ Width="525"
14
+ Height="350"
15
+ prism:ViewModelLocator.AutoWireViewModel="True">
16
+
17
+ <!-- prism:ViewModelLocator.AutoWireViewModel="True" があるからいらないはず -->
18
+ <!--<Window.DataContext>
19
+ <l:MainWindowViewModel />
20
+ </Window.DataContext>-->
21
+
22
+ <Window.Resources>
23
+ <!-- SelectionMode選択用データ(本題には無関係 違いを確認しやすいように) -->
24
+ <ObjectDataProvider
25
+ x:Key="selectionMode"
26
+ MethodName="GetValues"
27
+ ObjectType="{x:Type sys:Enum}">
28
+ <ObjectDataProvider.MethodParameters>
29
+ <x:Type TypeName="controls:SelectionMode" />
30
+ </ObjectDataProvider.MethodParameters>
31
+ </ObjectDataProvider>
32
+ </Window.Resources>
33
+
34
+ <Grid>
35
+ <Grid.ColumnDefinitions>
36
+ <ColumnDefinition />
37
+ <ColumnDefinition Width="2*" />
38
+ </Grid.ColumnDefinitions>
39
+ <Grid.RowDefinitions>
40
+ <RowDefinition Height="Auto" />
41
+ <RowDefinition />
42
+ </Grid.RowDefinitions>
43
+
44
+ <Grid>
45
+ <Grid.ColumnDefinitions>
46
+ <ColumnDefinition Width="Auto" />
47
+ <ColumnDefinition />
48
+ </Grid.ColumnDefinitions>
49
+ <Label
50
+ Margin="5"
51
+ VerticalAlignment="Center"
52
+ Content="表題" />
53
+ <TextBox
54
+ Grid.Column="1"
55
+ Margin="5"
56
+ VerticalAlignment="Center"
57
+ Text="{Binding Txt_Title, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
58
+ TextWrapping="Wrap" />
59
+ </Grid>
60
+
61
+ <Grid Grid.Column="1">
62
+ <Grid.ColumnDefinitions>
63
+ <ColumnDefinition Width="Auto" />
64
+ <ColumnDefinition />
65
+ <ColumnDefinition Width="Auto" />
66
+ </Grid.ColumnDefinitions>
67
+ <Label
68
+ Margin="5"
69
+ VerticalAlignment="Center"
70
+ Content="Memo" />
71
+ <TextBox
72
+ Grid.Column="1"
73
+ Margin="5"
74
+ VerticalAlignment="Center"
75
+ Text="{Binding Txt_Memo, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
76
+ TextWrapping="Wrap" />
77
+ <Button
78
+ Grid.Column="2"
79
+ MinWidth="56"
80
+ Margin="5"
81
+ Command="{Binding ExecuteCommand}"
82
+ Content="追加" />
83
+ </Grid>
84
+
85
+ <Grid Grid.Row="1">
86
+ <Grid.RowDefinitions>
87
+ <RowDefinition Height="Auto" />
88
+ <RowDefinition />
89
+ </Grid.RowDefinitions>
90
+
91
+ <!-- SelectionMode選択 -->
92
+ <ComboBox
93
+ x:Name="comboBox"
94
+ Margin="5"
95
+ ItemsSource="{Binding Source={StaticResource selectionMode}}"
96
+ SelectedIndex="0" />
97
+ <ListBox
98
+ x:Name="lst_Title"
99
+ Grid.Row="1"
100
+ Margin="5"
101
+ DisplayMemberPath="Title"
102
+ IsSynchronizedWithCurrentItem="True"
103
+ ItemsSource="{Binding TaskList}"
104
+ SelectionMode="{Binding SelectedValue, ElementName=comboBox}" />
105
+ </Grid>
106
+
107
+ <Grid Grid.Row="1" Grid.Column="1">
108
+ <Grid.RowDefinitions>
109
+ <RowDefinition />
110
+ <RowDefinition Height="Auto" />
111
+ </Grid.RowDefinitions>
112
+
113
+ <!-- SelectedItems をもらう -->
114
+ <ListBox Margin="5" ItemsSource="{Binding SelectedItems, ElementName=lst_Title}">
115
+ <ListBox.ItemTemplate>
116
+ <DataTemplate>
117
+ <StackPanel>
118
+ <TextBlock FontWeight="Bold" Text="{Binding Title}" />
119
+ <TextBlock Text="{Binding Detail}" />
120
+ </StackPanel>
121
+ </DataTemplate>
122
+ </ListBox.ItemTemplate>
123
+ </ListBox>
124
+
125
+ <!-- lst_Title が SelectionMode="Single" ならこれもあり -->
126
+ <StackPanel Grid.Row="1">
127
+ <TextBlock
128
+ Margin="5"
129
+ FontWeight="Bold"
130
+ Text="{Binding TaskList/Title}" />
131
+ <TextBlock Margin="5" Text="{Binding TaskList/Detail}" />
132
+ </StackPanel>
133
+ </Grid>
134
+ </Grid>
135
+ </Window>
136
+ ```
137
+
138
+ ```cs
139
+ using System.Collections.ObjectModel;
140
+ using Prism.Commands;
141
+ using Prism.Mvvm;
142
+
143
+ namespace Questions284783.ViewModels
144
+ {
145
+ public class MainWindowViewModel : BindableBase
146
+ {
147
+ private string txt_Title;
148
+ public string Txt_Title
149
+ {
150
+ get => txt_Title;
151
+ set
152
+ {
153
+ if(SetProperty(ref txt_Title, value))
154
+ ExecuteCommand.RaiseCanExecuteChanged();
155
+ }
156
+ }
157
+
158
+ private string txt_Memo;
159
+ public string Txt_Memo
160
+ {
161
+ get => txt_Memo;
162
+ set
163
+ {
164
+ if(SetProperty(ref txt_Memo, value))
165
+ ExecuteCommand.RaiseCanExecuteChanged();
166
+ }
167
+ }
168
+
169
+ public ObservableCollection<Task> TaskList { get; } = new ObservableCollection<Task>();
170
+
171
+ public DelegateCommand ExecuteCommand { get; private set; }
172
+
173
+ public MainWindowViewModel()
174
+ {
175
+ // 検証時面倒なので先入れ^^;
176
+ TaskList.Add(new Task { Title = "aaa", Detail = "111" });
177
+ TaskList.Add(new Task { Title = "bbb", Detail = "222" });
178
+ TaskList.Add(new Task { Title = "ccc", Detail = "333" });
179
+
180
+ ExecuteCommand = new DelegateCommand(Execute, CanExecute);
181
+ }
182
+
183
+ private void Execute()
184
+ {
185
+ TaskList.Add(new Task { Title = Txt_Title, Detail = Txt_Memo });
186
+
187
+ Txt_Title = "";
188
+ Txt_Memo = "";
189
+
190
+ ExecuteCommand.RaiseCanExecuteChanged();
191
+ }
192
+
193
+ private bool CanExecute() => !string.IsNullOrEmpty(Txt_Title);
194
+ }
195
+
196
+ public class Task
197
+ {
198
+ public string Title { get; set; }
199
+ public string Detail { get; set; }
200
+ }
201
+ }
202
+ ```
203
+
204
+
205
+ バインディング中のスラッシュ`{Binding TaskList/Title}`については↓あたりを参照してください(説明放棄^^;
206
+ [方法: 階層データでマスター詳細パターンを使用する - WPF | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/framework/wpf/data/how-to-use-the-master-detail-pattern-with-hierarchical-data)
207
+ [WPF4.5入門 その56「コレクションのバインディング」 - かずきのBlog@hatena](https://blog.okazuki.jp/entry/2014/10/29/220236) 最後のほうの「現在の選択項目をバインディングする方法」
208
+
209
+ ---
210
+
211
+ ここまでは`View`だけでの対応ですが、選択されているというのが重要な情報の場合(ファイルに選択情報も保存して次回復元する等)は、別の手のほうがいいかもしれません。
212
+
213
+ `Task`クラスに`bool IsSelected`プロパティを用意して、`lst_Title`では`ListBoxItem`の`IsSelected`にバインドし、`lst_Detail`では`ListBoxItem`の`Visibility`にバインドします。
214
+ どちらの`ListBox`も`TaskList`がソースですが、`lst_Detail`では未選択のものは無いように見えます。
215
+ ちょっとずるいようですが、割とポピュラーな手段だと思います。もし気になるようでしたら追記しますので言ってください。
216
+
217
+ ---
218
+
219
+ > ソースコードに改善点ありましたらご指摘願います。
220
+
221
+ `prism:ViewModelLocator.AutoWireViewModel="True"`があるので`<l:MainWindowViewModel />`で入れる必要はないはずです。
222
+
223
+ ぐちゃぐちゃ`Margin`(`Margin="66,5,122,5"`のようなもの)はよろしくないです(`Margin="5"`や`Margin="5,2"`のようなすっきりしたものならOKです)
224
+ ユーザーのフォント設定やウィンドウのリサイズ等で、文字が見切れたりレイアウト崩れの原因になります。
225
+ はっきり言って面倒なのですが、入れ子`Grid`等で地道にレイアウトしてください。
226
+
227
+ `Width="56"`もフォントによっては見切れるので、`MinWidth="56"`にしておくと安心です。
228
+
229
+ C#コードは特にないです^^
230
230
  `ReactiveProperty`を使えば、プロパティのごちゃっとしたところを緩和できそうです。