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

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

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

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

MVVM

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

WPF

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

Q&A

解決済

2回答

8595閲覧

WPFによるコマンドデータバインディングの書き方について

nanase

総合スコア123

C#

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

MVVM

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

WPF

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

0グッド

1クリップ

投稿2016/09/01 14:33

編集2016/09/01 15:23

こんにちは。
プロジェクトはModel、View、ViewModelの3つで構成されており、ViewModelがModelのインスタンスを保持してViewに公開しています。
その上で質問です。

View:

XAML

1<Window x:Class="TestWpf.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:local="clr-namespace:TestWpf" 7 mc:Ignorable="d" 8 Title="MainWindow" Height="350" Width="525"> 9 <Window.DataContext> 10 <local:ViewModel/> 11 </Window.DataContext> 12 <Grid DataContext="{Binding M}"> 13 <Grid.ColumnDefinitions> 14 <ColumnDefinition Width="0.5*"></ColumnDefinition> 15 <ColumnDefinition Width="0.5*"></ColumnDefinition> 16 </Grid.ColumnDefinitions> 17 <Grid.RowDefinitions> 18 <RowDefinition Height="0.5*"></RowDefinition> 19 <RowDefinition Height="0.5*"></RowDefinition> 20 </Grid.RowDefinitions> 21 <Grid Row="0" Column="0"> 22 <TextBlock Text="{Binding Name}"></TextBlock> 23 </Grid> 24 <Grid Row ="0" Column="1"> 25 <TextBlock Text="{Binding Name}"></TextBlock> 26 </Grid> 27 <Grid Row="1" Column="0"> 28 <TextBlock Text="{Binding Name}"></TextBlock> 29 </Grid> 30 <Grid Row="1" Column="1"> 31 <!-- コマンドを追加したい --> 32 </Grid> 33 </Grid> 34</Window>

ViewModel:

C#

1 class ViewModel:INotifyPropertyChanged { 2 public event PropertyChangedEventHandler PropertyChanged; 3 4 private ICommand Command { 5 get; 6 set; 7 } 8 private Model _m; 9 10 public Model M { 11 get { 12 return this._m; 13 } 14 set { 15 this._m = value; 16 OnPropertyChanged("M"); 17 } 18 } 19 20 public ViewModel() { 21 this.M = new Model(); 22 this.M.Name = "nana"; 23 this.Command = new RoutedUICommand(); 24 } 25 26 27 private void OnPropertyChanged( string name ) { 28 var handler = this.PropertyChanged; 29 handler?.Invoke( this, new PropertyChangedEventArgs( name ) ); 30 } 31 }

Model:

C#

1 class Model :INotifyPropertyChanged { 2 public event PropertyChangedEventHandler PropertyChanged; 3 4 private string _name; 5 6 public string Name { 7 get { 8 return this._name; 9 } 10 set { 11 this._name = value; 12 OnPropertyChanged("Name"); 13 } 14 } 15 16 17 private void OnPropertyChanged( string name ) { 18 var handler = this.PropertyChanged; 19 handler?.Invoke( this, new PropertyChangedEventArgs( name ) ); 20 } 21 }

Viewは上記のような田の字に区画がわかれており、それを包括するGridでデータコンテキストにModelのインスタンスを設定しています。
そのうち田の字の一区画に

XAML

1<Button Content="改名" Command="{Binding Command}"></Button>

のようなボタンを設置し、コマンドをBindingしたいと考えています。
ここで問題になるのが、12行目のDataContextの設定です。

XAML

1<Grid DataContext="{Binding M}">

これのおかげでViewModel直下のプロパティであるCommandをBindingすることが出来ません。

この場合、それぞれの田の字の区画を構成するGrid一つ一つのDataContextにModelをBindingするべきなのでしょか。
出来ることなら他の全てのコントロールのBindingはModel下のプロパティに対するものなので、外側のGridでDataContext={Binding M}をしてしまい、ボタンのBindingのみ例外というような記述にしたいのですが、それは可能なのでしょうか。

それとも、MVVMやBindingの考え方から間違っているのでしょうか。
御指南御指摘よろしくお願いいたします。

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

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

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

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

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

guest

回答2

0

ベストアンサー

RelativeSourceで、祖先を検索して、そのDataContextを使用するという事が可能です。

ex) Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Command}"

MainWindow.xaml (Windowタグ内部のみ)

xaml

1<Window.DataContext> 2 <local:ViewModel/> 3</Window.DataContext> 4<Grid DataContext="{Binding M}"> 5 <Grid.ColumnDefinitions> 6 <ColumnDefinition Width="*"/> 7 <ColumnDefinition Width="*"/> 8 </Grid.ColumnDefinitions> 9 <Grid.RowDefinitions> 10 <RowDefinition Height="*"/> 11 <RowDefinition Height="*"/> 12 </Grid.RowDefinitions> 13 <Grid Grid.Row="0" Grid.Column="0"><TextBlock Text="{Binding Name}"></TextBlock></Grid> 14 <Grid Grid.Row="1" Grid.Column="0"><TextBlock Text="{Binding Name}"></TextBlock></Grid> 15 <Grid Grid.Row="0" Grid.Column="1"><TextBlock Text="{Binding Name}"></TextBlock></Grid> 16 <Grid Grid.Row="1" Grid.Column="1"> 17 <Button Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Command}"></Button> 18 </Grid> 19</Grid>

MainWindow.xaml.cs

cs

1namespace tt46441_WPF_AncestorCommand { 2 /// <summary> 3 /// MainWindow.xaml の相互作用ロジック 4 /// </summary> 5 public partial class MainWindow : Window { 6 public MainWindow() { 7 InitializeComponent(); 8 } 9 } 10 11 public class ViewModel { 12 public ViewModel (){ 13 this.Command = new HelloWorldCommand(); 14 this.M = new ModelData { Name = "TeraTail" }; 15 } 16 17 public ICommand Command { get; set; } 18 19 class HelloWorldCommand : ICommand { 20 public event EventHandler CanExecuteChanged; 21 22 public bool CanExecute(object parameter) { 23 return true; 24 } 25 public void Execute(object parameter) { 26 MessageBox.Show("Hello, World"); 27 } 28 } 29 30 public class ModelData { 31 private string name = ""; 32 public string Name { get { return name; } set { name = value; } } 33 } 34 public ModelData M { get; set; } 35 } 36}

投稿2016/09/01 15:40

flied_onion

総合スコア2604

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

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

nanase

2016/09/01 21:58

ありがとうございます。まさに知りたかったことです。
guest

0

c#

1<Grid DataContext="{Binding M}"> 2<!-- 省略 --> 3 <Grid Row="0" Column="0"> 4 <TextBlock Text="{Binding Name}"></TextBlock> 5 </Grid> 6<!-- 省略 --> 7 <Grid Row="1" Column="1"> 8 <!-- コマンドを追加したい --> 9 </Grid> 10</Grid>

と書いているところを、

c#

1<Grid> 2<!-- 省略 --> 3 <Grid Row="0" Column="0"> 4 <TextBlock Text="{Binding M.Name}"></TextBlock> 5 </Grid> 6<!-- 省略 --> 7 <Grid Row="1" Column="1"> 8 <Button Content="改名" Command="{Binding Command}"></Button> 9 </Grid> 10</Grid>

と書くのはいかがでしょうか?

投稿2016/09/01 15:38

TAKA_0921

総合スコア234

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問