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

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

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

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

Q&A

解決済

1回答

515閲覧

C# WPFで動作するComboBoxのBindingをWinFormsで実装する方法について

bon7347

総合スコア1

C#

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

1グッド

0クリップ

投稿2024/12/14 22:00

編集2024/12/14 23:49

実現したいこと

Visual Studio Community 2022 Preview 17.13.0 Preview2.0
.net9.0 C# LangVersionはPreview(Projectファイルに追加) CommunityToolkit.Mvvm 8.40 の環境で.net8.0から強化されたWinFormsのBindingについて検証しています。ComboBoxでのBindingで、WPFでは実現できるのですが、WinFormsでは実現できないことがあります。

発生している問題・分からないこと

ViewModelは同じ内容のものを使用しています。ComboBoxの選択を変更したときに、TextBoxに選択内容を表示しようとしています。WPFではドロップダウンリストで選択したものがTextBoxに表示できるのですが、WinFormsでは表示できません。WinFormsのComboBoxの仕様なのか、プログラムミスなのかわからない状況です。

該当のソースコード

WPF MainWindow.xaml

C#

1<Window x:Class="A02_DialogBinding.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:A02_DialogBinding" 7 mc:Ignorable="d" 8 Title="MainWindow" Height="450" Width="800"> 9 <Window.DataContext> 10 <local:MainViewModel /> 11 </Window.DataContext> 12 <Grid> 13 <TextBox HorizontalAlignment="Left" Margin="197,196,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Text="{Binding ComboSelectItem}"/> 14 <ComboBox HorizontalAlignment="Center" Margin="0,196,0,0" VerticalAlignment="Top" Width="120" ItemsSource="{Binding ComboItems}" SelectedItem="{Binding ComboSelectItem}"/> 15 </Grid> 16</Window>

WPF MainViewModel

C#

1using System.Collections.ObjectModel; 2using CommunityToolkit.Mvvm.ComponentModel; 3 4namespace A02_DialogBinding; 5 6public partial class MainViewModel : ObservableObject 7{ 8 public MainViewModel() 9 { 10 ComboItems = ["Item 1", "Item 2", "Item 3"]; 11 ComboSelectItem = ComboItems[2]; 12 } 13 14 /// <summary> 15 /// Combobox用Itemsのデータを保持するコレクション 16 /// </summary> 17 [ObservableProperty] 18 public partial ObservableCollection<string> ComboItems { get; private set; } 19 20 /// <summary> 21 /// Comboboxで選択されたItem 22 /// </summary> 23 [ObservableProperty] 24 public partial string ComboSelectItem { get; set; } 25}

WinForms Form3 TextBoxとComboBoxを配置

C#

1namespace Advance.Trial.Binding; 2 3public partial class Form3 : Form 4{ 5 private readonly Form3ViewModel? _viewModel; 6 7 public Form3() 8 { 9 InitializeComponent(); 10 11 _viewModel = new Form3ViewModel(); 12 comboBox1.DataBindings.Add(nameof(comboBox1.DataSource), _viewModel, nameof(_viewModel.ComboItems)); 13 comboBox1.DataBindings.Add(nameof(comboBox1.SelectedItem), _viewModel, nameof(_viewModel.ComboSelectItem), false, 14 DataSourceUpdateMode.OnPropertyChanged); 15 textBox1.DataBindings.Add(nameof(textBox1.Text), _viewModel, nameof(_viewModel.ComboSelectItem), false, 16 DataSourceUpdateMode.OnPropertyChanged); 17 } 18}

WinForms Form3ViewModel

C#

1using System.Collections.ObjectModel; 2using CommunityToolkit.Mvvm.ComponentModel; 3 4namespace Advance.Trial.Binding; 5 6public partial class Form3ViewModel : ObservableObject 7{ 8 public Form3ViewModel() 9 { 10 ComboItems = ["Item 1", "Item 2", "Item 3"]; 11 ComboSelectItem = ComboItems[2]; 12 } 13 14 /// <summary> 15 /// Combobox用Itemsのデータを保持するコレクション 16 /// </summary> 17 [ObservableProperty] 18 public partial ObservableCollection<string> ComboItems { get; private set; } 19 20 /// <summary> 21 /// Comboboxで選択されたItem 22 /// </summary> 23 [ObservableProperty] 24 public partial string ComboSelectItem { get; set; } 25}

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

terataildeで「CommunityToolkit」「MVVMToolkit」で検索しましたが該当するものがありませんでした。

補足

ソースは上から
WPF MainWindow.xaml
WPF MainViewModel
WinForms Form3 TextBoxとComboBoxを配置
WinForms Form3ViewModel
です。

TN8001👍を押しています

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

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

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

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

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

hqf00342

2024/12/15 03:06

MvvmToolKitの新しい機能を使っているのにちょっとびっくり(うれしい)ですが、 恐らくComboBoxで選択変更後、フォーカスを別のコントロールに移すとTextBoxに反映されませんか?
bon7347

2024/12/15 07:28

コメントありがとうございます。ご指摘の通りフォーカス移動でTextBoxに反映されました。WPFとは挙動が違いますが、WinFormsのComboBoxの仕様でしょうか。
hqf00342

2024/12/15 08:57

ComboBox.SelectedItemはフォーカスが移動するなどして値が確定したときに変更通知が走ります。 選択時に変更通知が欲しいのであればSelectedValueがその動きをしますが今回のコードであれば、 選択アイテム変更時にBinding変更させるように、例えば comboBox1.SelectionChangeCommitted += (s, _) => (s as ComboBox)?.DataBindings["SelectedItem"]?.WriteValue(); のようなイベント処理を1行追記してもよいかもしれません。
bon7347

2024/12/15 13:31

ありがとうございます。hqg00342さんのブログ、とても助かっています。
guest

回答1

0

ベストアンサー

WinFormsのComboBoxの仕様なのか、プログラムミスなのかわからない状況です。

cs

1public partial class MainViewModel : ObservableObject 2{ 3 partial void OnComboSelectItemChanged(string value) => Debug.WriteLine(value);

としておくと、選択の変更だけでは呼ばれないことが確認できます。
SelectedIndexSelectedValueは即時に変わるのですが、SelectedItemはなぜか即時には変わらないようです。
SelectedItemChangedイベントがないことからもそういう仕様なのかもしれません。

提示のコードならTextにバインドすることで、意図通りの動きになりました。

文字列以外のデータ(色とか数値とか)も持つなら、SelectedValueにバインドするのも手かもしれません。

cs

1using System.Collections.ObjectModel; 2using CommunityToolkit.Mvvm.ComponentModel; 3 4namespace Qnzyewzsqfnzs05; 5 6public partial class Form1 : Form 7{ 8 private readonly ViewModel vm = new(); 9 10 public Form1() 11 { 12 InitializeComponent(); 13 14 comboBox1.DropDownStyle = ComboBoxStyle.DropDownList; 15 comboBox1.DataBindings.Add("DataSource", vm, nameof(vm.Items1)); 16 comboBox1.DataBindings.Add("SelectedItem", vm, nameof(vm.SelectedItem1), false, DataSourceUpdateMode.OnPropertyChanged); 17 textBox1.DataBindings.Add("Text", vm, nameof(vm.SelectedItem1), false, DataSourceUpdateMode.OnPropertyChanged); 18 19 comboBox2.DropDownStyle = ComboBoxStyle.DropDownList; 20 comboBox2.DataBindings.Add("DataSource", vm, nameof(vm.Items2)); 21 comboBox2.DataBindings.Add("Text", vm, nameof(vm.SelectedItem2), false, DataSourceUpdateMode.OnPropertyChanged); 22 textBox2.DataBindings.Add("Text", vm, nameof(vm.SelectedItem2), false, DataSourceUpdateMode.OnPropertyChanged); 23 24 comboBox3.DropDownStyle = ComboBoxStyle.DropDownList; 25 comboBox3.ValueMember = nameof(Item.Value); 26 comboBox3.DataBindings.Add("DataSource", vm, nameof(vm.Items3)); 27 comboBox3.DataBindings.Add("SelectedValue", vm, nameof(vm.SelectedItem3), false, DataSourceUpdateMode.OnPropertyChanged); 28 textBox3.DataBindings.Add("Text", vm, nameof(vm.SelectedItem3), false, DataSourceUpdateMode.OnPropertyChanged); 29 } 30} 31 32public partial class ViewModel : ObservableObject 33{ 34 public ObservableCollection<string> Items1 { get; } = ["Item 1", "Item 2", "Item 3"]; 35 [ObservableProperty] public partial string SelectedItem1 { get; set; } 36 37 public ObservableCollection<string> Items2 { get; } = ["Item 1", "Item 2", "Item 3"]; 38 [ObservableProperty] public partial string SelectedItem2 { get; set; } 39 40 public ObservableCollection<Item> Items3 { get; } = [new("Item 1"), new("Item 2"), new("Item 3")]; 41 [ObservableProperty] public partial string SelectedItem3 { get; set; } 42 43 public ViewModel() 44 { 45 SelectedItem1 = Items1[^1]; 46 SelectedItem2 = Items2[^1]; 47 SelectedItem3 = Items3[^1].Value; 48 } 49 50 //partial void OnSelectedItem1Changed(string value) => Debug.WriteLine(value); 51} 52 53public record Item(string Value);

アプリ動画

投稿2024/12/15 09:16

編集2024/12/20 20:04
TN8001

総合スコア10031

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

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

bon7347

2024/12/15 13:23

ありがとうございました。サンプルまで作成して頂き、感謝しています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問