トップ回答者
【ComboBoxColumnとTextColumnを連動させる方法】

質問
-
お世話になります。
ComboBoxColumnの値を変更した場合、連動してTextColumnの値も変更させようとしています。
ComboBxoColumn上でEnterキーやTABキー(TextColumnの編集状態)にした場合、
TextColumnの値も変更されるのですが
マウスを使って、フォーカスを移動させた場合、TextColumnの値が変更されないようです。
XAMLの設定は、以下のように設定しています。
<my:DataGrid.Columns> <my:DataGridComboBoxColumn Header="CD" x:Name="mComboBox" SelectedValueBinding="{Binding FirstName}" DisplayMemberPath="Code" SelectedValuePath="FirstName" > </my:DataGridComboBoxColumn> <my:DataGridTextColumn Header="名前" Binding="{Binding FirstName}" /> </my:DataGrid.Columns>
通常の、ComboBoxとLabelを連動させている箇所を参考にTextColumnのバインド記述を
Binding="{Binding ElementName=mComboBox, Path=SelectedItem.FirstName}
のようにしてみたのですが、動作していないようです。
連動させる方法をご存知の方がいらっしゃいましたら、宜しくお願いします。- 編集済み Kinsuma 2009年4月27日 2:42
回答
-
えムナウさんがおしゃっている【ComboBox用のテーブルを作成】とは
単に、DataSetのインスタンスを別に作成しちゃえば良いってことでしょうか。Dim Grid用 As 社員(型付DataSet) Dim ComboBox用 As 社員(型付DataSet) ※型付DataSetもxsdを作成するようにしました
もともと、Grid用のDataSetをComboBoxにも適用させていたのですが
動作確認している時に、挙動がおかしいのに気づき、現在は上記のように別で作成している状態です。
挙動がおかしいのに気づいて別インスタンスを作成していたんですね。
失礼しました。以前の質問の状況でやられていたとばかり思っていました。
ComboBoxの選択は mComboBox.ItemsSource DisplayMemberPath SelectedValuePath で決まります。
私にとって不思議なのは、TextColumnを<my:DataGridTextColumn Header="名前" Binding="{Binding FirstName}" />
のように設定しただけで、ComboBoxのCodeから紐づくFirstNameと連携されているのか?
このFirstNameはGrid用のDataSetと関連付けられているはずなのに...
むしろこの、TextColumnのBinding方法が違うのでは...に行き着いてしまったわけです。
設定としては、正しいのでしょうか??
※Windowsアプリでも確認してみたいと思います。
ComboBox用のテーブルの一つのRowを選択したことになります。
ComboBoxではそのRowの SelectValuePath で指定したColumnの値が SelectedValue に設定されます。
DataGridは その行について DataGridComboBoxColumn の SelectedValue が変わったことを検知して SelectedValueBinding に指定されている Columnの値を変更します。
したがって DataGridTextColumn も Grid用のテーブルの選択されている Row に従った値に変わります。
つまり、ComboBox用のテーブルは値は変化しません。
Grid用のテーブルの FirstName のみが ComboBox で選択された値に変わります。
Grid用のテーブルの Code も変化しません。(XAML上に出てきませんから)
えムナウ@わんくま同盟 Microsoft MVP Visual Studio C# Since 2005/01-2009/12- 回答としてマーク Kinsuma 2009年4月28日 8:45
-
DataRow は INotifyPropertyChanged をサポートしていないので 実はWPFで使うのにあまり適さないんです。
ObservableCollection (INotifyCollectionChanged) と INotifyPropertyChanged を使ったクラスを使用してください。
こんな風に INotifyPropertyChanged をちゃんと実行すれば大丈夫です。
データベースからなら LinqToSQL とか LinqToEntities とかは INotifyCollectionChanged や INotifyPropertyChanged サポートしています。
Public Class PersonRow Implements ComponentModel.INotifyPropertyChanged Public Sub New() _code = "" _firstName = "" End Sub Public Sub New(ByVal code As String, ByVal firstName As String) _code = code _firstName = firstName End Sub Public Event PropertyChanged As ComponentModel.PropertyChangedEventHandler Implements ComponentModel.INotifyPropertyChanged.PropertyChanged Public Sub NotifyPropertyChanged(ByVal propertyName As String) RaiseEvent PropertyChanged(Me, New ComponentModel.PropertyChangedEventArgs(propertyName)) End Sub Private _code As String Public Property Code() As String Get Return _code End Get Set(ByVal value As String) If value <> _code Then _code = value NotifyPropertyChanged("Code") End If End Set End Property Private _firstName As String Public Property FirstName() As String Get Return _firstName End Get Set(ByVal value As String) If value <> _firstName Then _firstName = value NotifyPropertyChanged("FirstName") End If End Set End Property End Class
Dim list As New ObjectModel.ObservableCollection(Of PersonRow) list.Add(New PersonRow("001", "001さん")) list.Add(New PersonRow("002", "002さん")) list.Add(New PersonRow("003", "003さん")) list.Add(New PersonRow("004", "004さん")) DataGrid1.DataContext = list
えムナウ@わんくま同盟 Microsoft MVP Visual Studio C# Since 2005/01-2009/12
すべての返信
-
Windows のWPFToolkitで確認してみましたがマウスでの動作は正しくしています。
ただ、初期表示の段階からComboBoxを変更すると(たとえば001を002に)、code=001,FirstName=002さんになります。
もともとのcode=002,FirstName=002さんもあるのでSelectedValuePath="FirstName"がどっちを参照するかはDataGridの実装しだいになります。
そのような異常な状態での実験はやめて、ComboBox用のテーブルを作成することをお勧めします。
えムナウ@わんくま同盟 Microsoft MVP Visual Studio C# Since 2005/01-2009/12 -
えムナウさん たびたびお世話になります。
>そのような異常な状態での実験
すみませんです^^; WPFの動作が良く分からず投稿しております。
えムナウさんがおしゃっている【ComboBox用のテーブルを作成】とは
単に、DataSetのインスタンスを別に作成しちゃえば良いってことでしょうか。Dim Grid用 As 社員(型付DataSet) Dim ComboBox用 As 社員(型付DataSet) ※型付DataSetもxsdを作成するようにしました
もともと、Grid用のDataSetをComboBoxにも適用させていたのですが
動作確認している時に、挙動がおかしいのに気づき、現在は上記のように別で作成している状態です。
私にとって不思議なのは、TextColumnを<my:DataGridTextColumn Header="名前" Binding="{Binding FirstName}" />
のように設定しただけで、ComboBoxのCodeから紐づくFirstNameと連携されているのか?
このFirstNameはGrid用のDataSetと関連付けられているはずなのに...
むしろこの、TextColumnのBinding方法が違うのでは...に行き着いてしまったわけです。
設定としては、正しいのでしょうか??
※Windowsアプリでも確認してみたいと思います。- 編集済み Kinsuma 2009年4月28日 6:42 体裁
-
えムナウさんがおしゃっている【ComboBox用のテーブルを作成】とは
単に、DataSetのインスタンスを別に作成しちゃえば良いってことでしょうか。Dim Grid用 As 社員(型付DataSet) Dim ComboBox用 As 社員(型付DataSet) ※型付DataSetもxsdを作成するようにしました
もともと、Grid用のDataSetをComboBoxにも適用させていたのですが
動作確認している時に、挙動がおかしいのに気づき、現在は上記のように別で作成している状態です。
挙動がおかしいのに気づいて別インスタンスを作成していたんですね。
失礼しました。以前の質問の状況でやられていたとばかり思っていました。
ComboBoxの選択は mComboBox.ItemsSource DisplayMemberPath SelectedValuePath で決まります。
私にとって不思議なのは、TextColumnを<my:DataGridTextColumn Header="名前" Binding="{Binding FirstName}" />
のように設定しただけで、ComboBoxのCodeから紐づくFirstNameと連携されているのか?
このFirstNameはGrid用のDataSetと関連付けられているはずなのに...
むしろこの、TextColumnのBinding方法が違うのでは...に行き着いてしまったわけです。
設定としては、正しいのでしょうか??
※Windowsアプリでも確認してみたいと思います。
ComboBox用のテーブルの一つのRowを選択したことになります。
ComboBoxではそのRowの SelectValuePath で指定したColumnの値が SelectedValue に設定されます。
DataGridは その行について DataGridComboBoxColumn の SelectedValue が変わったことを検知して SelectedValueBinding に指定されている Columnの値を変更します。
したがって DataGridTextColumn も Grid用のテーブルの選択されている Row に従った値に変わります。
つまり、ComboBox用のテーブルは値は変化しません。
Grid用のテーブルの FirstName のみが ComboBox で選択された値に変わります。
Grid用のテーブルの Code も変化しません。(XAML上に出てきませんから)
えムナウ@わんくま同盟 Microsoft MVP Visual Studio C# Since 2005/01-2009/12- 回答としてマーク Kinsuma 2009年4月28日 8:45
-
DataRow は INotifyPropertyChanged をサポートしていないので 実はWPFで使うのにあまり適さないんです。
ObservableCollection (INotifyCollectionChanged) と INotifyPropertyChanged を使ったクラスを使用してください。
こんな風に INotifyPropertyChanged をちゃんと実行すれば大丈夫です。
データベースからなら LinqToSQL とか LinqToEntities とかは INotifyCollectionChanged や INotifyPropertyChanged サポートしています。
Public Class PersonRow Implements ComponentModel.INotifyPropertyChanged Public Sub New() _code = "" _firstName = "" End Sub Public Sub New(ByVal code As String, ByVal firstName As String) _code = code _firstName = firstName End Sub Public Event PropertyChanged As ComponentModel.PropertyChangedEventHandler Implements ComponentModel.INotifyPropertyChanged.PropertyChanged Public Sub NotifyPropertyChanged(ByVal propertyName As String) RaiseEvent PropertyChanged(Me, New ComponentModel.PropertyChangedEventArgs(propertyName)) End Sub Private _code As String Public Property Code() As String Get Return _code End Get Set(ByVal value As String) If value <> _code Then _code = value NotifyPropertyChanged("Code") End If End Set End Property Private _firstName As String Public Property FirstName() As String Get Return _firstName End Get Set(ByVal value As String) If value <> _firstName Then _firstName = value NotifyPropertyChanged("FirstName") End If End Set End Property End Class
Dim list As New ObjectModel.ObservableCollection(Of PersonRow) list.Add(New PersonRow("001", "001さん")) list.Add(New PersonRow("002", "002さん")) list.Add(New PersonRow("003", "003さん")) list.Add(New PersonRow("004", "004さん")) DataGrid1.DataContext = list
えムナウ@わんくま同盟 Microsoft MVP Visual Studio C# Since 2005/01-2009/12