次の方法で共有


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

質問

2011年12月10日土曜日 4:56

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

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

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

 

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

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

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

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

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

 

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

 

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

すべての返信 (2)

2011年12月10日土曜日 6:11 ✅回答済み | 1 票

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!)


2011年12月10日土曜日 8:41

gekka様

 

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

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

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

 

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

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

 

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

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