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

回答編集履歴

3

若干追記

2020/10/16 11:54

投稿

Automatic9045
Automatic9045

スコア313

answer CHANGED
@@ -84,7 +84,7 @@
84
84
  public MainWindow()
85
85
  {
86
86
  InitializeComponent();
87
- DataContext = new MainWindowViewModel();
87
+ DataContext = new MainWindowViewModel(); // DataContextに指定したクラスの変更通知を受け取り、自動的に表示に反映するようになります。
88
88
  }
89
89
  }
90
90
  ```
@@ -114,4 +114,8 @@
114
114
  ButtonClicked = new DelegateCommand(() => MessageBox.Show("ボタンが押されました"));
115
115
  }
116
116
  }
117
- ```
117
+ ```
118
+
119
+ MVVMパターンで開発する場合、変更通知はVM→V(とM→VM)で発生させることになります。
120
+ VがVMの変更通知を受け取る部分に関しては、XAMLコードをもとに自動的に処理してくれるので開発者はただVMにINotifyPropertyChangedを実装させてVのDataContextに指定するのみでOKです。
121
+ 一方、VMがMの変更通知を受け取る部分に関しては、VMのコンストラクター内などで`M.PropertyChanged += (sender, e) => { …略… };`とすることになります。

2

MVVMについて追記

2020/10/16 11:54

投稿

Automatic9045
Automatic9045

スコア313

answer CHANGED
@@ -44,4 +44,74 @@
44
44
  ```
45
45
 
46
46
  この他、Collectionの要素の変更を通知することができる`ObservableCollection`というものもあったりします。
47
- 詳しくは検索してみて下さい。
47
+ 詳しくは検索してみて下さい。
48
+
49
+ ##(追記)参考:MVVMに沿った設計
50
+ WPFアプリはMVVMという設計思想に沿って設計するのが一般的となっています。
51
+ MVVMはModel-View-ViewModelの略で、
52
+
53
+ - ウィンドウやユーザーコントロールなど、画面への表示に直接関与するクラスをView
54
+ - ViewにBindingするプロパティを持つクラスをViewModel
55
+ - ロジックなどを持つクラスをModel
56
+
57
+ というように、クラスのメンバの役割によってクラスを分離し、コードを読みやすくすることが出来ます。
58
+
59
+
60
+ 以下、MVVMパターンを適用して
61
+
62
+ - LabelにViewModelのValueを表示
63
+ - Buttonクリック時にViewModelのButtonClickedを実行
64
+
65
+ 以上の機能を実装したサンプルです。
66
+
67
+ 私がPrismerなのでPrismを利用して書きますが、各クラスは以下のような感じになります。
68
+ 実行環境が手元に無いので、もしかしたら動かないかもしれません。動かなかった場合はごめんなさい。
69
+
70
+ ###MainWindow (XAML)
71
+ ```XAML
72
+ <Window …略…>
73
+ <StackPanel>
74
+ <Label Content="{Binding Value}" />
75
+ <Button Command="{Binding ButtonClicked}" />
76
+ </StackPanel>
77
+ </Window>
78
+ ```
79
+
80
+ ###MainWindow (C#)
81
+ ```C#
82
+ public class MainWindow : Window
83
+ {
84
+ public MainWindow()
85
+ {
86
+ InitializeComponent();
87
+ DataContext = new MainWindowViewModel();
88
+ }
89
+ }
90
+ ```
91
+
92
+ ###ViewModel
93
+ ```C#
94
+ //using Prism.Mvvm;
95
+ //using Prism.Commands;
96
+
97
+ // BindableBaseがINotifyPropertyChangedを実装してくれています。
98
+ // MainWindowなどのDataContextにこのクラスのインスタンスを指定して下さい。
99
+ public class MainWindowViewModel : BindableBase
100
+ {
101
+ private string _Value = string.Empty;
102
+ public string Value
103
+ {
104
+ get => _Value;
105
+ set => SetProperty(ref _Value, value);
106
+ }
107
+
108
+ // MVVMでは、ボタンクリック時のメソッドなどもVMに書きます。
109
+ // Xaml内でButtonに「Command="{Binding ButtonClicked}"」を設定すると使えるようになります。
110
+ public DelegateCommand ButtonClicked { get; set; }
111
+
112
+ public MainWindowViewModel()
113
+ {
114
+ ButtonClicked = new DelegateCommand(() => MessageBox.Show("ボタンが押されました"));
115
+ }
116
+ }
117
+ ```

1

サンプルコードを追加

2020/10/16 11:43

投稿

Automatic9045
Automatic9045

スコア313

answer CHANGED
@@ -1,9 +1,47 @@
1
1
  こんばんは。
2
2
 
3
- >データが変更された場合、ほかのクラスにその変更を通知する必要があるクラス
3
+ > データが変更された場合、ほかのクラスにその変更を通知する
4
4
 
5
5
  INotifyPropertyChangedという、もろそのもののインターフェイスが存在します。
6
6
  WPFで開発しているとよくお世話になるものです。
7
7
 
8
8
  インターフェイスを実装するか、あるいはPrismなどの実装を補助するフレームワークを利用することで変更通知が飛ぶようになります。
9
+
10
+ ```C#
11
+ //using System.ComponentModel;
12
+ //using Prism.Mvvm;
13
+
14
+ // BindableBaseがINotifyPropertyChangedを実装してくれています。
15
+ public class Data : BindableBase
16
+ {
17
+ private string _Value = string.Empty;
18
+ public string Value
19
+ {
20
+ get => _Value;
21
+ set => SetProperty(ref _Value, value);
22
+ }
23
+ }
24
+
25
+ public class Observer
26
+ {
27
+ Data data = new Data();
28
+
29
+ public Observer()
30
+ {
31
+ data.PropertyChanged += (sender, e) =>
32
+ {
33
+ switch (e.PropertyName)
34
+ {
35
+ case nameof(Data.Value):
36
+ Console.WriteLine($"Valueプロパティの値が \"{data.Value}\" に変更されました");
37
+ break;
38
+ }
39
+ };
40
+
41
+ data.Value = "hello"; // ここで変更通知が発火されます
42
+ }
43
+ }
44
+ ```
45
+
46
+ この他、Collectionの要素の変更を通知することができる`ObservableCollection`というものもあったりします。
9
47
  詳しくは検索してみて下さい。