回答編集履歴

2

見直しキャンペーン中

2023/08/14 09:53

投稿

TN8001
TN8001

スコア9341

test CHANGED
@@ -1,6 +1,6 @@
1
1
  > 相手の発言が左、自分の発言が右に来るようにListBoxのStyleを動的に変更しようとしました。
2
2
 
3
- 正確には`ListBox`の`ItemContainerStyle`で`ListBoxItem`の`Style`を`DataTrigger`で変えるということですね?
3
+ 正確には`ListBox`の`ItemContainerStyle`で`ListBoxItem`の`Style`を`DataTrigger`で変えるということですね?
4
4
 
5
5
  > DataTriggerのValueはバインドできませんでした。(Bindingは使えないというエラーメッセージ)
6
6
 
@@ -16,7 +16,7 @@
16
16
 
17
17
  ---
18
18
 
19
- 前置きが長すぎましたが質問について、「wpf datatrigger value binding」で検索したところ↓がヒットしました。
19
+ 前置きが長すぎましたが質問について、「[wpf datatrigger value binding](https://www.google.co.jp/search?q=wpf+datatrigger+value+binding)」で検索したところ↓がヒットしました。
20
20
  [.net - Using binding for the Value property of DataTrigger condition - Stack Overflow](https://stackoverflow.com/questions/2240421/using-binding-for-the-value-property-of-datatrigger-condition)
21
21
 
22
22
  コンバータが必要なのがちょっと気になります^^;(ほかのアプローチも何かありそうですが

1

見直しキャンペーン中

2023/07/27 16:08

投稿

TN8001
TN8001

スコア9341

test CHANGED
@@ -1,365 +1,183 @@
1
1
  > 相手の発言が左、自分の発言が右に来るようにListBoxのStyleを動的に変更しようとしました。
2
-
3
-
4
2
 
5
3
  正確には`ListBox`の`ItemContainerStyle`で`ListBoxItem`の`Style`を`DataTrigger`で変えるということですね?
6
4
 
7
-
8
-
9
5
  > DataTriggerのValueはバインドできませんでした。(Bindingは使えないというエラーメッセージ)
10
-
11
-
12
6
 
13
7
  できなかったことも「試したこと」として提示いただけると、やりたいことがはっきりして回答しやすいです。
14
8
 
15
-
16
-
17
9
  > DynamicResourcesを使おうと思ったんですが、調べてもResoucesに単純なstringをバインドする方法が見つかりませんでした。
18
-
19
-
20
10
 
21
11
  こういうことか自信がありませんが、回答コードにはコメントで入れた通り結論はダメでした。
22
12
 
23
-
24
-
25
13
  > ※省略してあります
26
-
27
-
28
14
 
29
15
  もちろん全部出されても困りますが、もう少しないとこちらで再現コードを書く手間と認識があっているかの確信が持てないです^^;
30
16
 
17
+ ---
31
18
 
19
+ 前置きが長すぎましたが質問について、「wpf datatrigger value binding」で検索したところ↓がヒットしました。
20
+ [.net - Using binding for the Value property of DataTrigger condition - Stack Overflow](https://stackoverflow.com/questions/2240421/using-binding-for-the-value-property-of-datatrigger-condition)
21
+
22
+ コンバータが必要なのがちょっと気になります^^;(ほかのアプローチも何かありそうですが
23
+
24
+ ```xml
25
+ <Window
26
+ x:Class="Questions345940.MainWindow"
27
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
28
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
29
+ xmlns:local="clr-namespace:Questions345940"
30
+ xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes"
31
+ xmlns:sys="clr-namespace:System;assembly=mscorlib"
32
+ Width="400"
33
+ Height="600">
34
+ <Window.Resources>
35
+ <local:MultiValueEqualityConverter x:Key="multiValueEqualityConverter" />
36
+ <!--<sys:String x:Key="myname">dekaribon</sys:String>-->
37
+ </Window.Resources>
38
+ <Window.DataContext>
39
+ <local:DirectMessageViewModel />
40
+ </Window.DataContext>
41
+ <DockPanel>
42
+ <DockPanel DockPanel.Dock="Bottom">
43
+ <Button
44
+ Command="{Binding SendCommand}"
45
+ Content="send"
46
+ DockPanel.Dock="Right" />
47
+ <RadioButton
48
+ Content="dekaribon"
49
+ IsChecked="{Binding IsChecked.Value}"
50
+ Style="{StaticResource MaterialDesignChoiceChipRadioButton}" />
51
+ <RadioButton Content="TN8001" Style="{StaticResource MaterialDesignChoiceChipRadioButton}" />
52
+ <TextBox VerticalAlignment="Center" md:HintAssist.Hint="message" />
53
+ </DockPanel>
54
+
55
+ <ListBox md:ThemeAssist.Theme="Dark" ItemsSource="{Binding MessageInfos}">
56
+ <ListBox.ItemContainerStyle>
57
+ <Style BasedOn="{StaticResource MaterialDesignListBoxItem}" TargetType="ListBoxItem">
58
+ <Setter Property="HorizontalAlignment" Value="Left" />
59
+ <Style.Triggers>
60
+ <DataTrigger Value="True">
61
+ <DataTrigger.Binding>
62
+ <MultiBinding Converter="{StaticResource multiValueEqualityConverter}">
63
+ <Binding Path="Username" />
64
+ <Binding Path="DataContext.Account.Value.Username" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ListBox}}" />
65
+ </MultiBinding>
66
+ </DataTrigger.Binding>
67
+ <Setter Property="HorizontalAlignment" Value="Right" />
68
+ </DataTrigger>
69
+
70
+ <!-- XDG0062 'DynamicResourceExtension' は、有効なトリガーの条件ではありません。 -->
71
+ <!--<DataTrigger Binding="{Binding Username}" Value="{DynamicResource myname}">
72
+ <Setter Property="HorizontalAlignment" Value="Right" />
73
+ </DataTrigger>-->
74
+ </Style.Triggers>
75
+ </Style>
76
+ </ListBox.ItemContainerStyle>
77
+ <ListBox.ItemTemplate>
78
+ <DataTemplate>
79
+ <md:Card
80
+ Margin="2"
81
+ Padding="20"
82
+ md:ShadowAssist.ShadowDepth="Depth2">
83
+ <StackPanel>
84
+ <TextBlock HorizontalAlignment="Center" Text="{Binding Username}" />
85
+ <Separator Margin="2,5" />
86
+ <TextBlock Margin="10,0,0,0" Text="{Binding Message}" />
87
+ </StackPanel>
88
+ </md:Card>
89
+ </DataTemplate>
90
+ </ListBox.ItemTemplate>
91
+ </ListBox>
92
+ </DockPanel>
93
+ </Window>
94
+ ```
95
+
96
+ ```cs
97
+ using Reactive.Bindings;
98
+ using System;
99
+ using System.Globalization;
100
+ using System.Linq;
101
+ using System.Windows;
102
+ using System.Windows.Data;
103
+
104
+ namespace Questions345940
105
+ {
106
+ // [.net - Using binding for the Value property of DataTrigger condition - Stack Overflow](https://stackoverflow.com/questions/2240421/using-binding-for-the-value-property-of-datatrigger-condition)
107
+ public class MultiValueEqualityConverter : IMultiValueConverter
108
+ {
109
+ public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
110
+ => values?.All(o => o?.Equals(values[0]) == true) == true || values?.All(o => o == null) == true;
111
+ public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
112
+ => throw new NotImplementedException();
113
+ }
114
+
115
+ public class AccountData
116
+ {
117
+ public string Username { get; set; }
118
+ }
119
+
120
+ public class DirectMessageItem
121
+ {
122
+ public string Username { get; set; }
123
+ public string Message { get; set; }
124
+ }
125
+
126
+ public class DirectMessageViewModel
127
+ {
128
+ public ReactiveProperty<AccountData> Account { get; } = new();
129
+ public ReactiveCollection<DirectMessageItem> MessageInfos { get; } = new();
130
+ public ReactiveCommand<string> SendCommand { get; } = new();
131
+ public ReactiveProperty<bool> IsChecked { get; } = new(true);
132
+
133
+ public DirectMessageViewModel()
134
+ {
135
+ Account.Value = new() { Username = "dekaribon", };
136
+ MessageInfos.Add(new() { Username = "dekaribon", Message = "aaa", });
137
+ MessageInfos.Add(new() { Username = "TN8001", Message = "bbb", });
138
+
139
+ SendCommand.Subscribe(message =>
140
+ {
141
+ MessageInfos.Add(new()
142
+ {
143
+ Username = Account.Value.Username,
144
+ Message = message,
145
+ });
146
+ });
147
+
148
+ // アカウントチェンジ(不自然なチェンジだが、入れ替わりのテスト
149
+ IsChecked.Subscribe(x =>
150
+ {
151
+ Account.Value = x ? new() { Username = "dekaribon", }
152
+ : new() { Username = "TN8001", };
153
+ });
154
+ }
155
+ }
156
+
157
+ public partial class MainWindow : Window
158
+ {
159
+ public MainWindow() => InitializeComponent();
160
+ }
161
+ }
162
+ ```
32
163
 
33
164
  ---
34
165
 
35
-
36
-
37
- 前置きが長すぎましたが質問について、「wpf datatrigger value binding」で検索したところ↓がヒットしました。
38
-
39
- [.net - Using binding for the Value property of DataTrigger condition - Stack Overflow](https://stackoverflow.com/questions/2240421/using-binding-for-the-value-property-of-datatrigger-condition)
40
-
41
-
42
-
43
- コンバータが必要なのがちょっと気になります^^;(ほかのアプローチも何かありそうですが
44
-
45
-
46
-
47
- ```xaml
48
-
49
- <Window
50
-
51
- x:Class="Questions345940.MainWindow"
52
-
53
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
54
-
55
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
56
-
57
- xmlns:local="clr-namespace:Questions345940"
58
-
59
- xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes"
60
-
61
- xmlns:sys="clr-namespace:System;assembly=mscorlib"
62
-
63
- Width="400"
64
-
65
- Height="600">
66
-
67
- <Window.Resources>
68
-
69
- <local:MultiValueEqualityConverter x:Key="multiValueEqualityConverter" />
70
-
71
- <!--<sys:String x:Key="myname">dekaribon</sys:String>-->
72
-
73
- </Window.Resources>
74
-
75
- <Window.DataContext>
76
-
77
- <local:DirectMessageViewModel />
78
-
79
- </Window.DataContext>
80
-
81
- <DockPanel>
82
-
83
- <DockPanel DockPanel.Dock="Bottom">
84
-
85
- <Button
86
-
87
- Command="{Binding SendCommand}"
88
-
89
- Content="send"
90
-
91
- DockPanel.Dock="Right" />
92
-
93
- <RadioButton
94
-
95
- Content="dekaribon"
96
-
97
- IsChecked="{Binding IsChecked.Value}"
98
-
99
- Style="{StaticResource MaterialDesignChoiceChipRadioButton}" />
100
-
101
- <RadioButton Content="TN8001" Style="{StaticResource MaterialDesignChoiceChipRadioButton}" />
102
-
103
- <TextBox VerticalAlignment="Center" md:HintAssist.Hint="message" />
104
-
105
- </DockPanel>
106
-
107
-
108
-
109
- <ListBox md:ThemeAssist.Theme="Dark" ItemsSource="{Binding MessageInfos}">
110
-
111
- <ListBox.ItemContainerStyle>
112
-
113
- <Style BasedOn="{StaticResource MaterialDesignListBoxItem}" TargetType="ListBoxItem">
114
-
115
- <Setter Property="HorizontalAlignment" Value="Left" />
116
-
117
- <Style.Triggers>
118
-
119
- <DataTrigger Value="True">
120
-
121
- <DataTrigger.Binding>
122
-
123
- <MultiBinding Converter="{StaticResource multiValueEqualityConverter}">
124
-
125
- <Binding Path="Username" />
126
-
127
- <Binding Path="DataContext.Account.Value.Username" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ListBox}}" />
128
-
129
- </MultiBinding>
130
-
131
- </DataTrigger.Binding>
132
-
133
- <Setter Property="HorizontalAlignment" Value="Right" />
134
-
135
- </DataTrigger>
136
-
137
-
138
-
139
- <!-- XDG0062 'DynamicResourceExtension' は、有効なトリガーの条件ではありません。 -->
140
-
141
- <!--<DataTrigger Binding="{Binding Username}" Value="{DynamicResource myname}">
142
-
143
- <Setter Property="HorizontalAlignment" Value="Right" />
144
-
145
- </DataTrigger>-->
146
-
147
- </Style.Triggers>
148
-
149
- </Style>
150
-
151
- </ListBox.ItemContainerStyle>
152
-
153
- <ListBox.ItemTemplate>
154
-
155
- <DataTemplate>
156
-
157
- <md:Card
158
-
159
- Margin="2"
160
-
161
- Padding="20"
162
-
163
- md:ShadowAssist.ShadowDepth="Depth2">
164
-
165
- <StackPanel>
166
-
167
- <TextBlock HorizontalAlignment="Center" Text="{Binding Username}" />
168
-
169
- <Separator Margin="2,5" />
170
-
171
- <TextBlock Margin="10,0,0,0" Text="{Binding Message}" />
172
-
173
- </StackPanel>
174
-
175
- </md:Card>
176
-
177
- </DataTemplate>
178
-
179
- </ListBox.ItemTemplate>
180
-
181
- </ListBox>
182
-
183
- </DockPanel>
184
-
185
- </Window>
186
-
187
- ```
188
-
189
-
190
-
191
- ```C#
192
-
193
- using Reactive.Bindings;
194
-
195
- using System;
196
-
197
- using System.Globalization;
198
-
199
- using System.Linq;
200
-
201
- using System.Windows;
202
-
203
- using System.Windows.Data;
204
-
205
-
206
-
207
- namespace Questions345940
208
-
209
- {
210
-
211
- // [.net - Using binding for the Value property of DataTrigger condition - Stack Overflow](https://stackoverflow.com/questions/2240421/using-binding-for-the-value-property-of-datatrigger-condition)
212
-
213
- public class MultiValueEqualityConverter : IMultiValueConverter
214
-
215
- {
216
-
217
- public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
218
-
219
- => values?.All(o => o?.Equals(values[0]) == true) == true || values?.All(o => o == null) == true;
220
-
221
- public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
222
-
223
- => throw new NotImplementedException();
224
-
225
- }
226
-
227
-
228
-
229
- public class AccountData
230
-
231
- {
232
-
233
- public string Username { get; set; }
234
-
235
- }
236
-
237
-
238
-
239
- public class DirectMessageItem
240
-
241
- {
242
-
243
- public string Username { get; set; }
244
-
245
- public string Message { get; set; }
246
-
247
- }
248
-
249
-
250
-
251
- public class DirectMessageViewModel
252
-
253
- {
254
-
255
- public ReactiveProperty<AccountData> Account { get; } = new();
256
-
257
- public ReactiveCollection<DirectMessageItem> MessageInfos { get; } = new();
258
-
259
- public ReactiveCommand<string> SendCommand { get; } = new();
260
-
261
- public ReactiveProperty<bool> IsChecked { get; } = new(true);
262
-
263
-
264
-
265
- public DirectMessageViewModel()
266
-
267
- {
268
-
269
- Account.Value = new() { Username = "dekaribon", };
270
-
271
- MessageInfos.Add(new() { Username = "dekaribon", Message = "aaa", });
272
-
273
- MessageInfos.Add(new() { Username = "TN8001", Message = "bbb", });
274
-
275
-
276
-
277
- SendCommand.Subscribe(message =>
278
-
279
- {
280
-
281
- MessageInfos.Add(new()
282
-
283
- {
284
-
285
- Username = Account.Value.Username,
286
-
287
- Message = message,
288
-
289
- });
290
-
291
- });
292
-
293
-
294
-
295
- // アカウントチェンジ(不自然なチェンジだが、入れ替わりのテスト
296
-
297
- IsChecked.Subscribe(x =>
298
-
299
- {
300
-
301
- Account.Value = x ? new() { Username = "dekaribon", }
302
-
303
- : new() { Username = "TN8001", };
304
-
305
- });
306
-
307
- }
308
-
309
- }
310
-
311
-
312
-
313
- public partial class MainWindow : Window
314
-
315
- {
316
-
317
- public MainWindow() => InitializeComponent();
318
-
319
- }
320
-
321
- }
322
-
323
- ```
324
-
325
-
326
-
327
- ---
328
-
329
-
330
-
331
166
  以降は質問には関係ないんですが、コードを書いていて不思議に思ったことです。
332
-
333
-
334
167
 
335
168
  > あるSNSのアカウントごとにAPIを使用してダイレクトメッセージをLINE風に表示しようとしています。
336
169
 
337
-
338
-
339
170
  > AccountData.Usernameが自分のユーザー名、DirectMessageItem.Usernameが相手のユーザー名になります。
340
171
 
341
-
342
-
343
172
  私が理解できていないだけかもしれませんが、逆じゃないですか?
344
-
345
173
  「アカウントごと」というのは、`DirectMessageViewModel`ごとという意味ですよね?
346
-
347
174
  `DirectMessageViewModel`のリストがあり、自分<->Aさん・自分<->Bさん等になるんですよね?
348
-
349
175
  自分と相手しかいないのであれば、`Account.Username`に自明な自分より相手の名前があったほうが便利そうですが(それとも最初から複垢想定?^^;
350
176
 
351
-
352
-
353
177
  `Account`が`ReactiveProperty`なのも「あれ?」と思いました。
354
-
355
178
  変更される時があるということですかね?(`DirectMessageViewModel`は一つで使いまわす設計?)
356
-
357
-
358
179
 
359
180
  それを逆手にとって、回答コードは入れ替わりのテストができたのですが^^;
360
181
 
361
-
362
-
363
182
  あと`ThemeAssist.Theme="Dark"`の当て方はあっているんでしょうか?
364
-
365
183
  回答コードだと`ListBox`の選択が見えない(これは結果OKっぽい)のと、スクロールバーの色が見えなくなりました^^;