質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

3回答

3111閲覧

【WPF】【MVVM】Frameを使った際は親要素のDataContextを引き継がないのか

galmacher

総合スコア37

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

0グッド

0クリップ

投稿2018/11/10 15:29

各コントロールのDataContextプロパティは、自分自身にDataContextが設定されていない場合は、
親要素を辿っていってその親のDataContextを利用するという認識です。
例えばMainWindow.xamlのDataContextにMainWindowViewModelを設定した場合は、
MainWindow内に配置したtextboxやbuttonなどのDataContextにもMainWindowViewModelが設定されると思っています。
その流れで、以下のようにNavigationWindowのSourceにPage0を設定し、
Page0のDataContextにPage0ViewModelを指定しました。
Page0はさらにFrameで二つにわけてPage1とPage2を設定しています。
この場合、Page1とPage2のDataContextはPage0ViewModelになるはずだと思っていたのですが
実際にはnullになっているようです。

・そもそも親のDataContextを引き継ぐという理解が誤っているのでしょうか?
・Page1とPage2のDataContextに、Page0と同じPage0ViewModelインスタンスを指定するにはどうすればよいでしょうか?

xaml

1MainWindow.xaml 2<NavigationWindow x:Class="FrameTest.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 6 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 7 xmlns:local="clr-namespace:FrameTest" 8 mc:Ignorable="d" 9 Title="MainWindow" Height="450" Width="800" 10 Source="Page0.xaml"> 11</NavigationWindow>

xaml

1Page0.xaml 2 <Grid> 3 <Grid.ColumnDefinitions> 4 <ColumnDefinition /> 5 <ColumnDefinition /> 6 </Grid.ColumnDefinitions> 7 <Frame Source="Page1.xaml"></Frame> 8 <Frame Grid.Column="1" Source="Page2.xaml"></Frame> 9 </Grid>

C#

1Page0.xaml.cs 2namespace FrameTest 3{ 4 public partial class Page0 : Page 5 { 6 public Page0() 7 { 8 InitializeComponent(); 9 var Data = new Page0ViewModel(); 10 DataContext = Data; 11 } 12 } 13}

C#

1Page0ViewModel.cs 2namespace FrameTest 3{ 4 class Page0ViewModel 5 { 6 ReactiveProperty<String> TextInput { get; set; } = new ReactiveProperty<String>(); 7 ReactiveProperty<String> TextOutput { get; set; } 8 9 public Page0ViewModel() 10 { 11 this.TextOutput = this.TextInput 12 .Select(s => s != null ? s.ToUpper() : null) 13 .ToReactiveProperty(); 14 } 15 } 16}

xaml

1Page1.xaml 2 <Grid> 3 <TextBox Width="100" 4 Height="100" 5 Text="{Binding TextInput.Value , Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox> 6 </Grid>

xaml

1Page2.xaml 2 <Grid> 3 <TextBlock Width="100" 4 Height="100" 5 Text="{Binding TextOutput.Value}"></TextBlock> 6 </Grid>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

そもそも親のDataContextを引き継ぐという理解が誤っているのでしょうか?

ほとんどの場合引継がれますが、
page.DataContext not inherited from parent Frame?
にあるように Frame は isolated hosting (隔離されたホスト)だそうです。なのでこの場合 DataContext は引き継がれません。

試してないですが、 RelativeSource を使ってみるのはどうでしょう?

投稿2018/11/11 06:04

gaya-K

総合スコア449

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

galmacher

2018/11/11 09:11

ご回答ありがとうございます。 やはりFrameは特殊な例で引き継がれない仕様なのですね。 RelativeSource少しだけ使ってみましたがうまく出来ませんでした。 シングルトンなModelを作ってそこから引っ張って来る方法を勉強してみます。
guest

0

PageのDataContextなんだから同じインスタンスを設定しない限りは引き継ぐような挙動をすることが無いのが当然じゃないのかな、なんせPage1と2自身がお互いを見てるわけではないのだから
あと、同じViewModelを見る必要もないと思う
ModelをSingletonにしてデータはそこから引っ張り出して共有化して、ViewModelはそれぞれのViewで必要なデータだけModelから参照するようにすればいいんじゃないかな?

あと、どのバージョンで開発しているのかわからないけど、VS2015(C#6.0)以降だとしたら、以下の書き換えが使える

C#

1// これを 2s != null ? s.ToUpper() : null 3 4// これにするとすっきり 5s?.ToUpper() 6

++C++未確認飛行のnull条件演算子

投稿2018/11/11 01:43

len_souko

総合スコア1348

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

galmacher

2018/11/11 03:24

ご回答ありがとうございます。 ■PageのDataContextなんだから~ Page自体もTextBlockやButton等と同等に一つの「コントロール」なのかなと思っておりまして、親のDataContextを引き継ぐのかと思っていました。 (参考にしたURL:http://var.blog.jp/archives/67898983.html) やはりPageに関しては明示的に指定しない限り、親のインスタンスを見るわけではないのですね。 ■ModelをSingletonにして~ ありがとうございます!実はその方法について調べていてもやり方が全く分からなく、「そもそも子にDataContextは引き継がれるのではないか?」という疑問が浮かんで今横道に逸れていた状態です。結局そうするのが一般的なのですね…。 ■s?.ToUpper() 細かいところまで見ていただいて恐縮です。勉強になりました!
guest

0

Frameは、使ったことないのでわかりません。

・Page1とPage2のDataContextに、Page0と同じPage0ViewModelインスタンスを指定するにはどうすればよいでしょうか?

ViewModelLocatorを使う。


https://code.msdn.microsoft.com/windowsdesktop/MVVMMVVM-Light-ReactiveProp-e998b7b1

投稿2018/11/10 19:07

kiichi54321

総合スコア1984

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

galmacher

2018/11/11 03:25

ご回答ありがとうございます。 サンプル拝読してみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問