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

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

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

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

Q&A

解決済

1回答

10638閲覧

Wpf コンボボックスで選択値をbindingしたい

kota190

総合スコア3

WPF

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

1グッド

0クリップ

投稿2021/08/22 08:47

WPFで作成した画面へのBindingでのデータの入出力を勉強し始めました。

ComboBoxのBindingで分からないことがあります。

やりたいことは、コンボボックスの初期値をSelectedIndexを指定するのではなく、
Value値(DicValue)のBindingで設定したいのと、
選択した結果をTwowayで(DicValue)反映させたいです。

他のサイトで調べたところ、SelectedValueで初期値を設定できる記載があったのですが、
うまく初期値として設定されないのと、選択値変更時、
DicValueに変更後の"key"列が入ると思ったのですが設定されません。

WPF

1<Window x:Class="WpfApp1.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:WpfApp1" 7 mc:Ignorable="d" 8 Title="MainWindow" Height="450" Width="800"> 9 <Grid> 10 11 <StackPanel Height="40" Background="Aqua"> 12 <ComboBox x:Name="cmb1" ItemsSource="{Binding ComboDic,Mode=OneWay}" 13 SelectedValue="{Binding DicValue,Mode=TwoWay}" 14 SelectedValuePath="key" 15 DisplayMemberPath="Value" 16 SelectionChanged="cmb1_Changed" 17 /> 18 </StackPanel> 19 20 </Grid> 21</Window>

C#

1namespace WpfApp1 2{ 3 public partial class MainWindow : Window 4 { 5 /* コンボボックスでバインドテスト*/ 6 public Dictionary<string, string> ComboDic { get; set; } 7 public string DicValue { get; set; } 8 9 10 public string ListSelectedItem { get; set; } 11 12 public MainWindow() 13 { 14 /* DictionaryでBinding */ 15 ComboDic = new Dictionary<string, string>() 16 { 17 {"10","りんご"}, 18 {"20","みかん"}, 19 {"30","ぶどう"}, 20 }; 21 22 InitializeComponent(); 23 24 /* 初期値 みかん */ 25 DicValue = "20"; 26 27 DataContext = this; 28 } 29 30 private void cmb1_Changed(object sender, SelectionChangedEventArgs e) 31 { 32 var item = this.DicValue; 33 } 34 } 35} 36
TN8001👍を押しています

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

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

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

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

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

guest

回答1

0

ベストアンサー

DicValueに変更後の"key"列が入ると思ったのですが設定されません。

「XAML バインド エラー」ウィンドウにエラーが出ています。

重大度レベル データ コンテキスト バインド パス ターゲット ターゲット型 説明 ファイル 行 プロジェクト エラー KeyValuePair`2 key ComboBox.NoTarget Object 型 KeyValuePair`2 のオブジェクトに key プロパティが見つかりません。 \mainwindow.xaml 13 Questions355574

「XAML バインド エラー」ウィンドウが見つからなければ、「出力」ウィンドウでもいいです。

System.Windows.Data Error: 40 : BindingExpression path error: 'key' property not found on 'object' ''KeyValuePair`2' (HashCode=54645477)'. BindingExpression:Path=key; DataItem='KeyValuePair`2' (HashCode=54645477); target element is 'ComboBox' (Name=''); target property is 'NoTarget' (type 'Object')

keyが見つからないと言っています。そのためDicValueとバインドできていません。
指定するのはKeyです。

選択した結果をTwowayで(DicValue)反映させたいです。

TwoWayの意味が初期値の反映とUIからの変更のみであれば、今のまま(自動プロパティ)でいいです。
コードからも変更したい場合は、PropertyChangedを発砲する必要があります。

xml

1<Window 2 x:Class="Questions355574.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 Width="800" 6 Height="450"> 7 <StackPanel> 8 <ComboBox 9 DisplayMemberPath="Value" 10 ItemsSource="{Binding ComboDic}" 11 SelectedValue="{Binding DicValue}" 12 SelectedValuePath="Key" 13 SelectionChanged="cmb1_Changed" /> 14 <Button Click="Button_Click" Content="みかん" /> 15 </StackPanel> 16</Window>

cs

1using System.Collections.Generic; 2using System.ComponentModel; 3using System.Diagnostics; 4using System.Runtime.CompilerServices; 5using System.Windows; 6using System.Windows.Controls; 7 8namespace Questions355574 9{ 10 public partial class MainWindow : Window, INotifyPropertyChanged 11 { 12 public Dictionary<string, string> ComboDic { get; } 13 14 public string DicValue { get; set; } 15 //public string DicValue { get => _DicValue; set => Set(ref _DicValue, value); } 16 //private string _DicValue; 17 18 public MainWindow() 19 { 20 InitializeComponent(); 21 22 ComboDic = new Dictionary<string, string> 23 { 24 { "10", "りんご" }, 25 { "20", "みかん" }, 26 { "30", "ぶどう" }, 27 }; 28 DicValue = "20"; 29 30 DataContext = this; 31 } 32 33 private void cmb1_Changed(object sender, SelectionChangedEventArgs e) 34 { 35 Debug.WriteLine(DicValue); 36 } 37 38 private void Button_Click(object sender, RoutedEventArgs e) 39 { 40 // DicValue { get; set; }のほうではこの変更が反映されない! 41 // こういうことをしたい場合は、PropertyChangedを発砲する必要がある(コメントされているDicValueのほうを使う) 42 DicValue = "20"; 43 } 44 45 46 public event PropertyChangedEventHandler PropertyChanged; 47 protected void Set<T>(ref T storage, T value, [CallerMemberName] string propertyName = null) 48 { 49 if (Equals(storage, value)) return; 50 storage = value; 51 OnPropertyChanged(propertyName); 52 } 53 protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 54 } 55}

投稿2021/08/22 09:59

編集2023/07/28 16:45
TN8001

総合スコア9321

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

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

kota190

2021/08/24 10:48

ご回答ありがとうございます。 ご指摘いただいた箇所を修正することにより、意図した動作となりました。 また、発砲のケースについても提示いただいたコードにより動作を確認することができました。 1点質問があります。 初歩的な質問で申し訳ありません。 Bindingするデータは、publicで宣言する必要があるのでしょうか。 (private変数に変更するとうまく動作しませんでした。)
TN8001

2021/08/24 11:53

> Bindingするデータは、publicで宣言する必要があるのでしょうか。 今回はMainWindow が MainWindow 内のプロパティにバインドしているためそう見えても不思議ではありません。 しかし通常は ViewModel とバインドします。 xamlでのバインド(ItemsSource="{Binding ComboDic}")をコードで表現するとこうなります。 var binding = new Binding("ComboDic") { Source = this, }; BindingOperations.SetBinding(ComboBox, ComboBox.ItemsSourceProperty, binding); Sourceに自身を入れようがViewModelを入れようがそこに差はありません。 このアプリ(Questions355574.exe)から見たら、外部のアセンブリ BindingOperations(PresentationFramework.dll)がバインドを処理します。 そのため「public プロパティしか探さない」という設計にしたのだと思います。 技術的にはinternalやprivateでもできるはず(リフレクションベースなので)ですが、できるようにする必然性も特に感じませんね^^; [c# - Binding to an internal property? - Stack Overflow](https://stackoverflow.com/questions/19704149/binding-to-an-internal-property
kota190

2021/08/24 15:31

ありがとうございます。 ViewModelについて、これから勉強したいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問