none
DependencyPropertyChangedEventArgs の e.NewValue値を使って自身をキャストする RRS feed

  • 質問

  • お世話になります。

    ちょっと表題がわかりにくいと思いますので、どういう状況なのか説明します。

    WPFで新しい画面を出すときに以下のようなコードを使ってます。

    [呼び出されるSubWindowViewModel]

            public Func<bool> OpenDialogBox;
            public Action<bool> CloseDialogBox;
    
            static public bool ShowDialog()
            {
                var vm = new SubWindowViewModel();
                var v = new SubWindow();
                v.DataContext = vm;
                return vm.OpenDialogBox();
            }

    [SubWindow.xaml.cs]

            public SubWindow()
            {
                DataContextChanged += (object sender, DependencyPropertyChangedEventArgs e) =>
                    {
                        var vm = DataContext as SubWindowViewModel;
                        if (vm == null) throw new InvalidCastException();
    
                        vm.ShowDialogBox = () => ShowDialog() ?? false;
                        vm.CloseDialogBox = (p) => DialogResult = p;
                    };
                InitializeComponent();
            }

    これで、親ウィンドウのから「 SubWindowViewModel.ShowDialog() 」を呼ぶとダイアログが出てくるというものなのですが、ここで呼び出されるのが選択肢ダイアログで、名前の並んだリストからひとつ選択して戻る。というケースで(複数個所で使うけれど外見は同じなので)Viewを共有したくなりました。

    SubWindow.xaml.cs の

    var vm = DataContext as SubWindowViewModel;

    で、直接SubWindowViewModelって書いてしまっているので、ここを動的に変更したいのですが、引数のDependencyPropertyChangedEventArgs  e の値を見てみると e.NewValue の中身がViewModelでした。

    var vm = e.NewValue as SubWindowViewModel; //これでも動作する
    ただし、e.NewValueはobject型なのでそのままでは
                        vm.ShowDialogBox = () => ShowDialog() ?? false;
                        vm.CloseDialogBox = (p) => DialogResult = p;

    がコンパイラを通りません((dynamic)e.NewValueでも駄目)。 中身はViewModelなのでうまく vmに設定して ひとつのViewで済ませたいのですが、object型のe.NewValueをその中身の型でキャストするのはどのようにすれば良いでしょうか。



    • 編集済み 雷持 2015年11月30日 7:22 字句の追加
    2015年11月30日 6:58

回答

  • 通常はインターフェースを使うことになるでしょう。つまり、インターフェース型にキャストしてShowDialogBoxメソッド等を実行します。ただ、dynamic型もあるので、それを使う方法もありますが、コンパイル時にチェックがかからなくなります。

    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク 雷持 2015年12月1日 1:48
    2015年11月30日 7:32
    モデレータ

すべての返信

  • 通常はインターフェースを使うことになるでしょう。つまり、インターフェース型にキャストしてShowDialogBoxメソッド等を実行します。ただ、dynamic型もあるので、それを使う方法もありますが、コンパイル時にチェックがかからなくなります。

    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク 雷持 2015年12月1日 1:48
    2015年11月30日 7:32
    モデレータ
  • Livetを導入してMessengerを使うとVとVMをうまく分離できると思います
    その場合は以下のスレッドが参考になるでしょうか

    https://social.msdn.microsoft.com/Forums/ja-JP/2d0207e7-5156-4a24-8b50-2ed86d873c3b/mvvmmodel?forum=wpfja

    2015年11月30日 7:40
  • trapemiya さん、返信ありがとうございます。

    こういうインターフェイスを作って

        class IDialogViewModel
        {
            public Func<bool> ShowDialogBox { get; set; }
            public Action<bool> CloseDialogBox { get; set; }
        }

    ViewModelにくっつけて

        class SubWindowViewModel:IDialogViewModel
        {
                  //中略
        }

    SubWindow.xaml.cs の中で

            public SubWindow()
            {
                DataContextChanged += (object sender, DependencyPropertyChangedEventArgs e) =>
                    {
                        var vm = (IDialogViewModel)e.NewValue;
                        if (vm == null) throw new InvalidCastException();
    
                        vm.ShowDialogBox = () => ShowDialog() ?? false;
                        vm.CloseDialogBox = (p) => DialogResult = p;
                    };
                InitializeComponent();
            }

    と、することで動作させることができました(こういうやりかたでいいですよね?)。

    ありがとうございました。



    • 編集済み 雷持 2015年12月1日 4:18 コードの訂正
    2015年12月1日 1:53
  • せれ さん、返信ありがとうございます。

    Livetですか…名前は聞いたことがあります。Prismを使っているのでなんか機能がぶつかるものなのかなと思っていました。

    ViewModelがViewを知っている私が今やってる方法はちょっとどうなんだろ?と思っていたので、今色々作ってるものが一段落したら調べてみようと思います。

    2015年12月1日 1:58
  • なるほど、Prismを採用されていたんですね。

    PrismでViewModelからViewを操作する場合は以下の情報が参考になるかと思います。

    https://code.msdn.microsoft.com/MVVMPrism-ReactiveProperty-dc36af04

    http://blog.okazuki.jp/entry/20101011/1286777561

    http://www.pine4.net/Memo/Article/Archives/418





    • 編集済み せれ 2015年12月1日 4:16
    2015年12月1日 3:55
  • >と、することで動作させることができました(こういうやりかたでいいですよね?)。

    OKです。


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/

    2015年12月1日 4:08
    モデレータ
  • せれ さん ありがとうございます。

    PrismのInteractionRequestですか、難しそうですが調べてみます。

    trapemiya さん

    よかった。「外れ!」だったらどうしようかと。ありがとうございます。

    2015年12月1日 8:30