例えば……
WPFで画面にドラッグ&ドロップでファイルを投げた時の処理を例として。
ViewのXAMLで
<Window x:Class="AmazonToYamatoB2Converter.Views.View"
AllowDrop="True"
Drop="View_Drop">
<Window.DataContext>
<vm:ViewModel/>
</Window.DataContext>
<Grid>
<!-- 画面 -->
</Grid>
</Window>
ってして、コードビハインドでドラッグ&ドロップを処理しようとするんだけど
public partial class View : Window
{
public View()
{
InitializeComponent();
}
private void View_Drop(object sender, DragEventArgs e)
{
var dropFileList = (e.Data.GetData(DataFormats.FileDrop) as string[]).ToList();
// ここから先はViewModelの処理としたい
}
}
ドラッグ&ドロップで渡されたファイル(パス)の処理はViewModelの責務じゃないかなと思うんですよ。
Modelに渡したりとかするわけですし。
ViewModelクラスにはその為の処理としてpublic void AddDragAndDropsFiles(List<string> fileList)
ってメソッドが実装されているとします。
で、そのメソッド呼ぶ為にViewからViewModelを参照するわけです。
普通にViewクラスからViewModelクラスを参照する
private ViewModel VM
{
get { return this.DataContext as ViewModel; }
}
private void View_Drop(object sender, DragEventArgs e)
{
var dropFileList = (e.Data.GetData(DataFormats.FileDrop) as string[]).ToList();
// ここから先はViewModelの処理としたい
this.VM. AddDragAndDropsFiles(dropFileList);
}
まぁよくあるやつです。
これの面倒な点は、ViewModelって型を書かないと行けないって所です。
名前空間usingして、ViewModelの型を補完使って入力。(逆もある)
ViewModelの型を変更しくなったらコードビハインドも変更しないといけない。
ならInterfaceは?
書くの面倒だからコード例は出さない。
確かにそれでいいかもしれない。
でも、それも結局Interfaceの型を変更する場合同じ事なんですよね。
usingするのも変わらんし。
Iなんたらかんたら
ってのを沢山継承するViewModelになることないですか?
Behavior作れば?
書くの(ry
この辺りを参照して下さい。
確かにコードビハインドにコード書く必要もなくなるのいいかもね。
Interface書くのすら面倒臭がる俺にこんな長いコードを書けとか鬼か。
再利用性はあるかもしれない。
が、でもちょっと使いづらとかで機能追加してコードが読みづらくなるの、よくある話ですよね。
そもそもドラッグ&ドロップでのファイルの受け渡し程度にこんな量のコード書くの?
これでいいんじゃね?
C# 4.0からだけど、dynamicってキーワードがある。
これを使うと
private dynamic VM
{
get { return this.DataContext; }
}
private void View_Drop(object sender, DragEventArgs e)
{
var dropFileList = (e.Data.GetData(DataFormats.FileDrop) as string[]).ToList();
// ここから先はViewModelの処理としたい
this.VM.AddDragAndDropsFiles(dropFileList);
}
こうなる。
何が良いって、VMはViewModelクラスじゃなくてもpublic void AddDragAndDropsFiles(List<string> fileList)
メソッドを実装しているクラスならOKって所。
ViewがViewModelの型や実装を気にしなくて良い。
ViewModelの事を気にせずViewだけの実装を書いておいて、後ViewModel実装するって事も出来る。
なお、呼び出してるメソッドが実装されてなかったらコンパイルエラーは発生せず、実行時にRuntimeBinderException
という例外が発生します。
「C#という言語で、メソッド実装してなかったらコンパイルエラーじゃなくて実行時エラーになるのってどうなの?」
という指摘は最もだと思います。潔癖症には辛いかもしれない。
でも、InterfaceやBehaviorの作成よりは読みやすいし、書くコード量も少なくて済むので悪くないんじゃ無いかと思います。