トップ回答者
DataGridでセル単位にコントロールを指定

質問
-
お世話になっております。
VB.NETにてWPFアプリケーションの開発を行っております。
WPFでの開発は初となるのですが、自分自身のスキル不足もあいまって右往左往している状態です。
そこでDataGridに関する質問なのですが、
端的に言いまして、DataGridでセルごとにコントロールを変更することは可能なのでしょうか?
(同じ列にテキストボックスやコンボボックスを表示したい)
自分では調べつくしたつもりなのですが結局分かりませんでした。
(見落としているだけ?)
DataGridTemplateColumnを使えば、Column単位であればかなり自由に制御できることは理解できたのですが、、。
以上ですが、よろしくお願いします。
回答
-
DataGridTemplateColumnのCellEditingTemplateSelectorを指定することで対応可能です。
public partial class Window1 : Window { public Window1() { InitializeComponent(); List<Test> list = new List<Test>(); list.Add(new Test() { Value = 1 }); list.Add(new Test() { Value = 2 }); list.Add(new Test() { Value = "ABCD" }); this.DataContext = list; } } class Test { public object Value { get; set; } } class CustomCellTemplateSelectorBase : System.Windows.Controls.DataTemplateSelector { protected DataGrid GetDataGrid(DependencyObject container) { DataGrid dgv = null; DependencyObject dpo = container; while (dpo != null) { dgv = dpo as DataGrid; if (dgv != null) { return dgv; } dpo = System.Windows.Media.VisualTreeHelper.GetParent(dpo); } return null; } } class CustomCellTemplateSelector : CustomCellTemplateSelectorBase { public override DataTemplate SelectTemplate(object item, DependencyObject container) { DataGrid dgv = GetDataGrid(container); if (dgv != null) { return (DataTemplate)dgv.FindResource("block"); } return base.SelectTemplate(item, container); } } class CustomEditingCellTemplateSelector : CustomCellTemplateSelectorBase { public override DataTemplate SelectTemplate(object item, DependencyObject container) { DataGrid dgv = GetDataGrid(container); if (dgv != null) { Test test = dgv.CurrentCell.Item as Test; if (test != null) { if (test.Value is int) { //編集用のテンプレートとしてComboBoxを返す return (DataTemplate)dgv.FindResource("cbx"); } else if (test.Value is string) { //編集用のテンプレートとしてTextBoxを返す return (DataTemplate)dgv.FindResource("txb"); } } } return base.SelectTemplate(item, container); } }
<DataGrid ItemsSource="{Binding}" AutoGenerateColumns="false" IsReadOnly="false" RowHeight="20" > <DataGrid.Resources> <DataTemplate x:Key="cbx"> <ComboBox Text="{Binding Value}" /> </DataTemplate> <DataTemplate x:Key="txb"> <TextBox Text="{Binding Value}" /> </DataTemplate> <DataTemplate x:Key="block"> <TextBlock Text="{Binding Value}" /> </DataTemplate> <app:CustomEditingCellTemplateSelector x:Key="editSelector" /> <app:CustomCellTemplateSelector x:Key="viewSelector" /> </DataGrid.Resources> <DataGrid.Columns> <DataGridTemplateColumn Header="A" IsReadOnly="False" Width="50" CellEditingTemplateSelector="{StaticResource editSelector}" CellTemplateSelector ="{StaticResource viewSelector}"> <!-- 編集用のDataTemplateの選択クラスを指定 --> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid>
#CellTemplateSelectorも指定してないと編集できなかったバグ修正
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
すべての返信
-
DataGridTemplateColumnのCellEditingTemplateSelectorを指定することで対応可能です。
public partial class Window1 : Window { public Window1() { InitializeComponent(); List<Test> list = new List<Test>(); list.Add(new Test() { Value = 1 }); list.Add(new Test() { Value = 2 }); list.Add(new Test() { Value = "ABCD" }); this.DataContext = list; } } class Test { public object Value { get; set; } } class CustomCellTemplateSelectorBase : System.Windows.Controls.DataTemplateSelector { protected DataGrid GetDataGrid(DependencyObject container) { DataGrid dgv = null; DependencyObject dpo = container; while (dpo != null) { dgv = dpo as DataGrid; if (dgv != null) { return dgv; } dpo = System.Windows.Media.VisualTreeHelper.GetParent(dpo); } return null; } } class CustomCellTemplateSelector : CustomCellTemplateSelectorBase { public override DataTemplate SelectTemplate(object item, DependencyObject container) { DataGrid dgv = GetDataGrid(container); if (dgv != null) { return (DataTemplate)dgv.FindResource("block"); } return base.SelectTemplate(item, container); } } class CustomEditingCellTemplateSelector : CustomCellTemplateSelectorBase { public override DataTemplate SelectTemplate(object item, DependencyObject container) { DataGrid dgv = GetDataGrid(container); if (dgv != null) { Test test = dgv.CurrentCell.Item as Test; if (test != null) { if (test.Value is int) { //編集用のテンプレートとしてComboBoxを返す return (DataTemplate)dgv.FindResource("cbx"); } else if (test.Value is string) { //編集用のテンプレートとしてTextBoxを返す return (DataTemplate)dgv.FindResource("txb"); } } } return base.SelectTemplate(item, container); } }
<DataGrid ItemsSource="{Binding}" AutoGenerateColumns="false" IsReadOnly="false" RowHeight="20" > <DataGrid.Resources> <DataTemplate x:Key="cbx"> <ComboBox Text="{Binding Value}" /> </DataTemplate> <DataTemplate x:Key="txb"> <TextBox Text="{Binding Value}" /> </DataTemplate> <DataTemplate x:Key="block"> <TextBlock Text="{Binding Value}" /> </DataTemplate> <app:CustomEditingCellTemplateSelector x:Key="editSelector" /> <app:CustomCellTemplateSelector x:Key="viewSelector" /> </DataGrid.Resources> <DataGrid.Columns> <DataGridTemplateColumn Header="A" IsReadOnly="False" Width="50" CellEditingTemplateSelector="{StaticResource editSelector}" CellTemplateSelector ="{StaticResource viewSelector}"> <!-- 編集用のDataTemplateの選択クラスを指定 --> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid>
#CellTemplateSelectorも指定してないと編集できなかったバグ修正
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)