ViewのコードビハインドからViewModelの型や実装をを気にせずメソッド&プロパティにアクセスする


例えば……

WPFで画面にドラッグ&ドロップでファイルを投げた時の処理を例として。
ViewのXAMLで

View.xaml
<Window x:Class="AmazonToYamatoB2Converter.Views.View"
        AllowDrop="True"
        Drop="View_Drop">

    <Window.DataContext>
        <vm:ViewModel/>
    </Window.DataContext>

    <Grid>
        <!-- 画面 -->
    </Grid>
</Window>

ってして、コードビハインドでドラッグ&ドロップを処理しようとするんだけど

View.xaml.cs
    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クラスを参照する

View.xaml.cs
        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ってキーワードがある。
これを使うと

View.xaml.cs
        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の作成よりは読みやすいし、書くコード量も少なくて済むので悪くないんじゃ無いかと思います。