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

質問編集履歴

1

ベストアンサーにした回答に基づいて、解決時のコードを後ろに追記。

2022/01/30 01:41

投稿

ttact
ttact

スコア171

title CHANGED
File without changes
body CHANGED
@@ -1,3 +1,6 @@
1
+ 2022/01/30 10:40
2
+ 質問の末尾に解決コードを追記しました。
3
+
1
4
  ### 課題
2
5
  自作クラスのインスタンスをLabel.ContentやTextBlock.Textにバインディングしています。
3
6
  初期表示では期待通りの文字列が表示されますが、バインディングソース側を更新してPropertyChangedイベントを発行しても、画面に表示される文字列が更新されません。
@@ -147,4 +150,89 @@
147
150
 
148
151
  ### 環境
149
152
  Visual Studio Professional 2019 ver. 16.11.9
150
- .NET 5
153
+ .NET 5
154
+
155
+ ---
156
+
157
+ ### 解決時のコード
158
+ ```xml
159
+ <ComboBox
160
+ ItemsSource="{Binding Languages}"
161
+ SelectedIndex="{Binding SelectedLanguage, Mode=TwoWay}"
162
+ />
163
+ <Label
164
+ Content="{Binding MyText.Value}"
165
+ />
166
+ ```
167
+ 本番ではModelからイベント通知を受けて更新を行いたいので、Languageをオブジェクトにしてみました。本番ではRx.NETを使って、ViewModelの破棄と同時にイベント購読キーも破棄します。
168
+ ```C#
169
+ public class Language
170
+ {
171
+ public delegate void ChangedHandler(int language);
172
+ public event ChangedHandler? Changed;
173
+ private int _value;
174
+ public int Value
175
+ {
176
+ set
177
+ {
178
+ if(_value != value)
179
+ {
180
+ _value = value;
181
+ Changed?.Invoke(_value);
182
+ }
183
+ }
184
+ get => _value;
185
+ }
186
+ }
187
+
188
+ public abstract class Notifiable : INotifyPropertyChanged
189
+ {
190
+ // 前述のコードと同じなので、略。
191
+ }
192
+
193
+ public class I18nStr : Notifiable
194
+ {
195
+ private int _language;
196
+ private string[] _values;
197
+ public I18nStr(Language language, params string[] values)
198
+ {
199
+ _language = language.Value;
200
+ _values = values;
201
+ language.Changed += ChangeLanguage;
202
+ }
203
+ public string Value => _values[_language];
204
+ private void ChangeLanguage(int language)
205
+ {
206
+ if(_language != language)
207
+ {
208
+ _language = language;
209
+ RaisePropertyChanged(nameof(Value));
210
+ }
211
+ }
212
+ }
213
+
214
+ public class ViewModel : Notifiable
215
+ {
216
+ private readonly Language _language = new Language();
217
+ public I18nStr MyText { get; }
218
+ public IEnumerable<string> Languages => new string[] { "英語", "日本語" };
219
+ public int SelectedLanguage
220
+ {
221
+ set
222
+ {
223
+ if(_language.Value != value)
224
+ {
225
+ _language.Value = value;
226
+ RaisePropertyChanged();
227
+ }
228
+ }
229
+ get => _language.Value;
230
+ }
231
+
232
+ public ViewModel()
233
+ {
234
+ MyText = new I18nStr(_language, "en", "jp");
235
+ }
236
+ }
237
+ ```
238
+