###前提
最近、C#でWPFを使用しているプロジェクトに参加することになりましたが、
WPF(MVVMパターン)でのデータバインディングの方法が理解できず困っています。
(MVVMにはPrismやLivetなどのフレームワークを使わず、独自に類似の仕組みを作成して実現しているようです)
あまりに分からないことが多く、まともに質問もできない状態ですが…
せめて自分の状況を理解していただくために、理解していること・困っていることなどを下に書きます。
(が、状況を理解してもらうことが目的なので、読まなくても構いません)
このようなレベルの私に、理解の助けになるテキストやサイト等を教えてください。
(プロジェクトで作成されたコードを読んでも理解が追いつかないことから、「サンプルコードを読んで理解する」ことは難しいと思っています。だいたい解説が無いですし、あっても英語ですし…)
できれば、下で紹介しているXAMLコードのような書き方の解説がされているものが良いと思っています。
贅沢を言うようですが、日本語の解説が欲しいです。
(ある程度WPFの仕組みを理解をしているなら英語でも良いのですが、ほとんど理解できていない状況で英語の解説はキツいものがあります)
質問として失礼な形になっているかもしれませんが、切羽詰まっており藁にもすがりたい思いですのでお許し下さい。
###発生している問題
以下、非常に読みづらいですが、「このくらい何も分かっていないんだな」ということを理解して頂ければ十分です。
理解が困難な点が複数あります。
何が分からないのかも分からない状態なので、現状で分かっていることを書きます。
例えば、以下の様なXAMLがあります。
OrigUI:OrigButtonは、標準のButtonクラスを継承したものです。
同様に、OrigUI:OrigTreeViewも、標準のTreeViewクラスを継承したものです。
xaml
1<grid> 2 <OrigUI:OrigButton x:name="MyButton" DataContext="{Binding MyButton, Mode=TwoWay}" /> 3 <OrigUI:OrigTreeView x:name="MyTreeView" DataContext="{Binding MyTreeView, Mode=TwoWay}" /> 4<grid>
ここでは、ボタンやツリーにセットするデータはDataContextを経由するように書かれています。
ところがネットで検索をかけても、XAML上でDataContext="{Binding Xxx}"
と書かれている例はほとんどありません。
(恐らく、ここで躓いているのが理解が出来ない一番の原因だと思います)
コードビハインド(.xaml.cs)側では、このボタンやツリーのバインディングに関する処理は何も書かれていません。
(でも、画面上のUIによっては.xaml.csにそういった処理が書かれているものもあります。何が違うのか分かりません)
そもそも、XAML上でDataContextに指定したものは、何を指しているのでしょうか…
そもそもDataContextとは?というところが、ネット上の解説を読んでも理解できていません。
継承をしたボタンやツリーには、データを格納するためのデータクラスOrigButtonData
, OrigTreeViewData
があります。(Button
やTreeView
とは全く継承関係の無いクラスです)
どうやらMyButton
とOrigButtonData
のインスタンス、MyTreeView
とOrigTreeViewData
のインスタンスをバインディングし、ViewModelから画面上のボタンやツリーにアクセスする際には、OrigButtonData
やOrigTreeView
を使うようです。
ViewModelには、"MyButton"
や"MyTreeView"
という名前のプロパティが作られています。このせいで、「MyButtonとバインドする」と言われても、XAMLのx:Name
のことかXAMLのDataContext
のことかViewModelの"MyButton"
というプロパティのことか分かりません。
ところがOrigButtonDataやOrigTreeViewは、元のButton
やTreeView
とは全く関係のないクラスなので、Button
やTreeView
が本来持っているプロパティにアクセスすることができません。
例えばTreeView
を構築するためにはTreeView.ItemsSource
というプロパティにオブジェクトを挿入すれば良いのですが、ViewModelからはMyTreeView
にアクセスできないため、ツリーを構築できません。
そこで、OrigTreeViewData
にTreeItems
というプロパティを追加し、TreeView.ItemsSource
とOrigTreeViewData.TreeItems
をバインドします。
そうすることでViewModel側から本来アクセスできないはずのMyTreeView.ItemsSource
にデータを追加することができるようになります。
Button
やTreeView
には、もちろんこれ以外のプロパティも存在します。そのプロパティにViewModelからアクセスするためには、またデータクラスに対応するプロパティを追加して、バインドの設定が必要です。
どうやら元々のButton
やTreeView
が持っているプロパティにXxxProperty
という名前のプロパティが「ある場合」「ない場合」でバインディングの方法が異なるようです。複雑です。
Button
やTreeView
が持っているプロパティにViewModelからアクセスしたいものの、そのプロパティの型ではコンストラクタの使用が禁止されていると、データクラスでその型のインスタンスを作れないため、バインドができません。
またアクセスしたいプロパティがgetter
しか持っておらず、値のセットができず途方に暮れることもあります。
ここでバインドを行うためには、データクラス・ViewModel・継承したMyButton
MyTreeView
のそれぞれにもバインディングの設定が必要です。
OnPropertyChanged
とかNotifyPropertyChanged
とか…DependencyProperty
なんてものも登場します。
複雑すぎて理解ができません。理解が追いつかず、「プロパティの変更を通知する」と言われても何のことだか分かっていません。
そもそも、XAMLではOrigButton
やOrigTreeView
というクラスを使っているのに、ViewModelから操作するのはOrigButtonData
やOrigTreeViewData
という全く継承関係のないクラスです。なぜViewModelからOrigButton
やOrigTreeView
クラスのオブジェクトを操作できるようになっていないのか理解に苦しみます。
(どうやら、ViewModelからは本当に必要なプロパティのみ操作できるようになることがメリットのようですが…)
この場合、例えばTreeView
の中にListがあり、そのリストの中身をバインドしてViewModelから操作したい…という場合、もう複雑すぎて手も足も出せません。
(例えばMyTreeView.Nodes[0].NodeItem
というものがあったとして、ViewModelからOrigTreeViewData
を経由してアクセスするためには何をどうバインドしたら良いのか分かりません。)
(Nodes
に対応するプロパティをデータクラスに作って…どうやってMyTreeView.Nodes
とバインドするの?バインドできたとしても、さらにリストのそれぞれの要素のNodeItem
とデータクラスをバインドする方法は…?)
(そもそも、何をしたらMyTreeView
とOrigTreeViewData
が結びついたのか分かっていないので、混乱に混乱を重ねて理解どころではありません…)
非常に長くなりましたが、自分の「分かっているところ」「分かっていないところ」は、だいたいこんな感じです。

回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/08/25 15:41
2016/08/25 16:09
2016/08/31 12:39
2016/08/31 13:21