ネタ元:【WPF】ViewからViewModelへViewのインスタンスを渡す(CommandParameter経由編)
と、ここでハタと思い付いた。あるクラスを用意し、その依存関係プロパティにViewのインスタンスを突っ込み、そのクラスでViewModelにそのインスタンスを渡してやればいいんじゃないかと。そのクラスはちょうどViewからViewModelへViewのインスタンスを橋渡しする働きをするわけだ。
明日にでも試してみよう。今日はこれから飲み会なんで。
飲み会の隙を伺って書いてみた。
using System.Windows;
namespace WpfModelViewApplication1.ViewModels
{
public static class あるクラス
{
#region ViewModelを保持するプロパティ
public static object GetViewModel(DependencyObject obj)
{
return (object)obj.GetValue(ViewModelProperty);
}
public static void SetViewModel(DependencyObject obj, object value)
{
obj.SetValue(ViewModelProperty, value);
}
public static readonly DependencyProperty ViewModelProperty =
DependencyProperty.RegisterAttached("ViewModel", typeof(object), typeof(あるクラス), new UIPropertyMetadata(null, PropertyChanged));
#endregion
#region ViewModelのViewをセットするプロパティ名
public static string GetPropertyPath(DependencyObject obj)
{
return (string)obj.GetValue(PropertyPathProperty);
}
public static void SetPropertyPath(DependencyObject obj, string value)
{
obj.SetValue(PropertyPathProperty, value);
}
public static readonly DependencyProperty PropertyPathProperty =
DependencyProperty.RegisterAttached("PropertyPath", typeof(string), typeof(あるクラス), new UIPropertyMetadata(null, PropertyChanged));
#endregion
#region プロパティ変更時の処理
private static void PropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
// viewはsenderのはず
object view = sender;
// viewmodelと
object viewModel = GetViewModel(sender);
// プロパティ名をとって
string property = GetPropertyPath(sender);
if (view == null || viewModel == null || property == null)
{
// 3つ設定されてなかったら何もしない
return;
}
// viewmodelにviewを設定する
var prop = viewModel.GetType().GetProperty(property);
prop.SetValue(viewModel, view, null);
}
#endregion
}
}
もうちょっとイケテル感じには出来るけど、お昼休みの限られた時間でということなので暫定版!使い方は以下の通り。
ViewModelにViewを受け入れるプロパティを定義!(IMainViewがViewが実装するインターフェース)
public class MainViewModel : ViewModelBase
{
// Viewを設定するプロパティ
public IMainView MainView { get; set; }
}
そして、XAML側に以下のような定義を足す。
<Window x:Class="WpfModelViewApplication1.Views.MainView"
...略...
xmlns:local="clr-namespace:WpfModelViewApplication1.ViewModels"
local:あるクラス.ViewModel="{Binding}"
local:あるクラス.PropertyPath="MainView"
Title="Main Window" Height="400" Width="800">
...略...
</Window>
これで完成。
後は、ViewModel側の適当なメソッドでViewを自由自在に弄れます。
# あとでやるかもしれない改良案
# ViewModelとProperty名を保持するクラスを作って、そいつを添付プロパティとして設定するといいかもしれない。
# <あるクラス.ViewModelMapping>
# <ViewModelとProperty名を保持するクラス ViewModel=”{Binding}” Property名=”MainView” />
# <あるクラス.ViewModelMapping>
# 後で