none
DataGridでセル単位にコントロールを指定 RRS feed

  • 質問

  • お世話になっております。

    VB.NETにてWPFアプリケーションの開発を行っております。

    WPFでの開発は初となるのですが、自分自身のスキル不足もあいまって右往左往している状態です。

     

    そこでDataGridに関する質問なのですが、

    端的に言いまして、DataGridでセルごとにコントロールを変更することは可能なのでしょうか?

    (同じ列にテキストボックスやコンボボックスを表示したい)

    自分では調べつくしたつもりなのですが結局分かりませんでした。

    (見落としているだけ?)

     

    DataGridTemplateColumnを使えば、Column単位であればかなり自由に制御できることは理解できたのですが、、。

     

    以上ですが、よろしくお願いします。

    2011年12月10日 4:56

回答

  • 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!)
    • 編集済み gekkaMVP 2011年12月10日 7:04
    • 回答の候補に設定 山本春海 2011年12月14日 1:17
    • 回答の候補の設定解除 山本春海 2011年12月14日 1:17
    • 回答としてマーク 山本春海 2011年12月14日 1:17
    2011年12月10日 6:11

すべての返信

  • 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!)
    • 編集済み gekkaMVP 2011年12月10日 7:04
    • 回答の候補に設定 山本春海 2011年12月14日 1:17
    • 回答の候補の設定解除 山本春海 2011年12月14日 1:17
    • 回答としてマーク 山本春海 2011年12月14日 1:17
    2011年12月10日 6:11
  • gekka様

     

    返信いただきありがとうございます!

    そして返信が遅れて申し訳ありません。(別作業に追われておりました、、)

    こんなにはやく返信をいただけるとは思ってもいませんでした。

     

    しかもコードまで作成(自分の知らない間にバグ修正まで)していただいて、、

    さっそく試させていただいたのですが、同じ列にコンボボックスとテキストボックスが表示されました。

     

    中身の理解ができておりませんので、コードを見ながらじっくりと勉強させていただきます。

    非常に助かりました。gekka様、ありがとうございます!

    2011年12月10日 8:41