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

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

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

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

データバインディング

データソースと、アプリケーションやウェブページ(ウェブアプリケーション)のユーザインタフェースを静的または動的に結合する技術です。

WPF

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

Q&A

解決済

3回答

5314閲覧

[WPF]コードビハインド以外のクラスのバインディングについて

Coriander

総合スコア12

C#

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

データバインディング

データソースと、アプリケーションやウェブページ(ウェブアプリケーション)のユーザインタフェースを静的または動的に結合する技術です。

WPF

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

0グッド

1クリップ

投稿2017/06/18 08:54

###発生している問題
WPF初心者です。
コードビハインド以外のクラスのプロパティをシンプルにバインドする方法があれば知りたいです。

サンプルとしてMainWindow.xaml, MainWindow.xaml.cs, Class1.csの3つを作成しています。
MainWindow.xamlのComboboxにはコードビハインドのListをバインドし、TextBlockにはClass1の変数をバインドしたいと思っています。
単純に考えると、以下でいけると思います。
DataContext = this;
TextBlock1.DataContext = class1;

ただし、上記方法ではもしxamlのバインド先が増えると
TextBlock1.DataContext = class1;
TextBlock2.DataContext = class1;
TextBlock3.DataContext = class1;
:
と少しかっこ悪いコードになってしまいます。
シンプルにバインドする方法はありますでしょうか。
また、初歩的な質問になりますが、本ソースコードのようにコードビハインド・別クラスをごちゃまぜでバインドさせるのは良くない実装方法なのでしょうか。

よろしくお願いします。
以下ソースコードです。
(質問用にサンプルを作成したため読みにくいコードになっています。すみません。)

###ソースコード
MainWindow.xaml

<Grid> <Grid.RowDefinitions> <RowDefinition Height="283*"/> <RowDefinition Height="37*"/> </Grid.RowDefinitions> <ComboBox Margin="286,135,0,0" VerticalAlignment="Top" Width="120" ItemsSource="{Binding TestList}"/> <TextBlock HorizontalAlignment="Left" Name="TextBlock1" Margin="111,141,0,0" TextWrapping="Wrap" Text="{Binding val}" VerticalAlignment="Top"/> <Button Content="Button" Margin="261,235,181,0" VerticalAlignment="Top" Width="75" Click="increment"/> <TextBlock HorizontalAlignment="Left" Name="TextBlock2" Margin="151,241,0,0" TextWrapping="Wrap" Text="{Binding val}" VerticalAlignment="Top"/> </Grid>

MainWindow.xaml.cs

public partial class MainWindow : Window { public Class1 class1; public List<string> TestList { get; set; } public MainWindow() { Initdata(); InitializeComponent(); DataContext = this; TextBlock1.DataContext = class1; TextBlock2.DataContext = class1; } private void Initdata() { class1 = new Class1(); TestList = new List<string>() { "a", "b", "c" }; } private void increment(object sender, RoutedEventArgs e) { class1.val += 1; } }

Class1.cs

public class Class1:INotifyPropertyChanged { public Class1() { val = 0; } private int _val; public int val { get { return _val; } set { _val = value; RaisePropertyChanged("val"); } } public event PropertyChangedEventHandler PropertyChanged; private void RaisePropertyChanged(String propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } }

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

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

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

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

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

guest

回答3

0

ベストアンサー

バインディングは、XAMLの木構造に従って、親のDataContextを引き継ぎます。
そのため、親にあたるところだけのDataContextをバイディングするだけで、子も変わります。

DataContextという名前の通り、DataContextはデータの文脈なんです。

こういう仕様なので、複数のクラスをバインドするのは当然よくやります。
ただ、コードビハインド側からは、やるのは、どうしてもできないときで、基本はXAML側で指定します。

投稿2017/06/18 14:37

kiichi54321

総合スコア1984

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

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

Coriander

2017/06/19 12:51

ありがとうございます。これが当然だと思ってましたが、無知って怖いですね。。。
guest

0

質問内容が把握しきれていないので、的外れだったらゴメンなさい。

TextBlock1.DataContext = class1;
TextBlock2.DataContext = class1;
TextBlock3.DataContext = class1;

のような記述を綺麗にしたいということであれば、kiichi54321さんの仰るとおり、親のDataContextを引き継ぐので、以下ではどうでしょうか。

MainWindow.xaml (適当に書き換えています)

xaml

1 <Grid.RowDefinitions> 2 <RowDefinition /> 3 <RowDefinition /> 4 </Grid.RowDefinitions> 5 <ComboBox VerticalAlignment="Top" ItemsSource="{Binding TestList}"/> 6 <!-- 親の同じオブジェクトをDataContextに指定したいElementを格納する親パネル --> 7 <StackPanel Name="ParentPanel" Grid.Row="1"> 8 <TextBlock HorizontalAlignment="Left" Name="TextBlock1" TextWrapping="Wrap" Text="{Binding val}"/> 9 <TextBlock HorizontalAlignment="Left" Name="TextBlock2" TextWrapping="Wrap" Text="{Binding val}"/> 10 <Button Content="Button" VerticalAlignment="Top" Width="75" Click="increment"/> 11 </StackPanel>

MainWindow.xaml.cs

C#

1public MainWindow() 2{ 3 Initdata(); 4 InitializeComponent(); 5 DataContext = this; 6 7 //ParentPanelのDataContext に class1をセット 8 //配下にあるTextBlock1,2にも引き継がれる 9 ParentPanel.DataContext = class1; 10}

ただし、hihijijiさん、kiichi54321さんが仰るとおり、こういう指定はどうしても仕方の場合以外やらないようが良いです。
通常ViewModelを定義してxaml内での指定で完結したほうが良いと思います。

投稿2017/06/19 00:09

ebiryo

総合スコア797

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

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

Coriander

2017/06/19 12:52

ありがとうございます。親要素云々の意味がよくわかりました。
guest

0

バインディングは普通XAML側に書きます。
詳しくは、「MVVM入門」をキーワードにwebページを検索してください。

投稿2017/06/18 11:02

hihijiji

総合スコア4150

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

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

Coriander

2017/06/19 12:49

ありがとうございます。良さそうなページを見つけたので勉強してみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問