【WPF】データグリッドにコンボボックス列を定義してリストを表示してみた

公開日:2019-07-07
最終更新:2019-07-07
※この記事は外部サイト(https://www.doraxdora.com/blog/2017/10/14/...)からのクロス投稿です

今回はデータグリッドにコンボボックスを表示したいと思います。

チェックボックスと同様、デフォルトで「DataGridComboBoxColumn」がありますが、
同じ理由(2回クリックしないと変更できない)で「DetaGridTemplateColumn」を利用したいと思います。

プログラムは次の記事のものを流用します。
【WPF】データグリッドにチェックボックスを表示する

※DBはSQLiteに変更してます

スタイルの修正

StyleDic.xaml

    <!-- データグリッド:通常 -->  
    <Style x:Key="grid-normal" TargetType="DataGrid">  
        <Setter Property="VerticalAlignment" Value="Top" />  
        <Setter Property="HorizontalAlignment" Value="Left" />  
        <Setter Property="Grid.Row" Value="1" />  
        <Setter Property="HorizontalScrollBarVisibility" Value="Visible" />  
        <Setter Property="AutoGenerateColumns" Value="False" />  
        <Setter Property="IsReadOnly" Value="False" />  
        <Setter Property="CanUserAddRows" Value="False"/>  
        <Setter Property="AlternationCount" Value="1" />  
        <Setter Property="AlternatingRowBackground" Value="#B2CEEBF7" />  
        <Setter Property="SelectionMode" Value="Single" />  
        <Setter Property="VerticalGridLinesBrush" Value="Gray" />  
        <Setter Property="HorizontalGridLinesBrush" Value="Gray" />  
    </Style>  
    <Style TargetType="DataGridCell">  
        <Setter Property="BorderThickness" Value="0" />  
        <Setter Property="FocusVisualStyle" Value="{x:Null}" />  
        <Setter Property="Height" Value="25" />  
        <Setter Property="Template">  
            <Setter.Value>  
                <ControlTemplate TargetType="{x:Type DataGridCell}">  
                    <Grid Background="{TemplateBinding Background}">  
                        <ContentPresenter VerticalAlignment="Center" Margin="4,4,4,4" />  
                    </Grid>  
                </ControlTemplate>  
            </Setter.Value>  
        </Setter>  
    </Style>  

    <Style x:Key="dgc-combo" TargetType="DataGridCell">  
        <Setter Property="BorderThickness" Value="0" />  
        <Setter Property="FocusVisualStyle" Value="{x:Null}" />  
        <Setter Property="Height" Value="25" />  
        <Setter Property="Template">  
            <Setter.Value>  
                <ControlTemplate TargetType="{x:Type DataGridCell}">  
                    <Grid Background="{TemplateBinding Background}">  
                        <ContentPresenter VerticalAlignment="Center" Margin="0" />  
                    </Grid>  
                </ControlTemplate>  
            </Setter.Value>  
        </Setter>  
    </Style>  

データグリッドを編集可能(行追加不可)にし、データグリッド内のコンボボックス用定義を追加。

画面の修正

MainWindow.xaml

<Mah:MetroWindow x:Class="WpfApp1.MainWindow"  
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
        xmlns:local="clr-namespace:WpfApp1"  
        xmlns:Mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"  
        mc:Ignorable="d"  
        Title="一覧" Height="350" Width="530"  
        GlowBrush="{DynamicResource AccentColorBrush}"  
        Icon="/WpfApp1;component/Resource/Cat.ico"  
        BorderThickness="1"  
        >  
    <Window.Resources>  
        <ResourceDictionary Source="/Style/StyleDic.xaml"/>  
    </Window.Resources>  
    <Grid Height="350" Width="530" Margin="0,1,-10,-33">  
        <Grid.Resources>  
            <local:KindConverter x:Key="KindConv"/>  
        </Grid.Resources>  
        <Rectangle x:Name="rec_overlay" Width="530" Height="330" Style="{StaticResource rec-overlay}" />  
        <Mah:ProgressRing x:Name="loading_image" Style="{StaticResource pgr-normal}"/>  
        <Label Content="名前:" Margin="10,10,0,0" Style="{StaticResource lb-normal}"/>  
        <TextBox x:Name="search_name" Margin="56,12,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120"  Style="{StaticResource MetroTextBox}"/>  
        <Label Content="種別:" Margin="201,10,0,0" Style="{StaticResource lb-normal}"/>  
        <ComboBox x:Name="search_kind" Margin="252,12,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="125"  Style="{StaticResource MetroComboBox}" SelectedIndex="0" />  
        <Button x:Name="search_button" Content="検索" HorizontalAlignment="Left" Margin="432,12,0,0" VerticalAlignment="Top" Width="75"  Click="search_button_Click" Style="{DynamicResource SquareButtonStyle}"/>  
        <DataGrid Name="dataGrid" HorizontalAlignment="Left" Margin="10,43,0,0" Width="497" Height="225" Style="{StaticResource grid-normal}" >  
            <DataGrid.Columns>  
                <DataGridTemplateColumn IsReadOnly="True" Header="選択" Width="50">  
                    <DataGridTemplateColumn.CellTemplate>  
                        <DataTemplate>  
                            <CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" VerticalAlignment="Center" />  
                        </DataTemplate>  
                    </DataGridTemplateColumn.CellTemplate>  
                </DataGridTemplateColumn>  
                <DataGridTextColumn Binding="{Binding No}" ClipboardContentBinding="{x:Null}" Header="No" IsReadOnly="True" Width="40" />  
                <DataGridTextColumn Binding="{Binding Name}" ClipboardContentBinding="{x:Null}" Header="名前" IsReadOnly="True" Width="80"/>  
                <DataGridTemplateColumn IsReadOnly="True" Header="性別"  CellStyle="{StaticResource dgc-combo}" Width="50">  
                    <DataGridTemplateColumn.CellTemplate>  
                        <DataTemplate>  
                            <ComboBox Name="cmbGender" ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}, Path=DataContext.GenderList, Mode=OneWay}"  
                                      DisplayMemberPath="Name" SelectedValuePath="Cd" SelectedValue="{Binding Sex}" Width="50"/>  
                        </DataTemplate>  
                    </DataGridTemplateColumn.CellTemplate>  
                </DataGridTemplateColumn>  
                <DataGridTextColumn Binding="{Binding Age}" ClipboardContentBinding="{x:Null}" Header="年齢" IsReadOnly="True" Width="40"/>  
                <DataGridTextColumn Binding="{Binding Kind, Converter={StaticResource KindConv}}" ClipboardContentBinding="{x:Null}" Header="種別" IsReadOnly="True" Width="110"/>  
                <DataGridTextColumn Binding="{Binding Favorite}" ClipboardContentBinding="{x:Null}" Header="好物" IsReadOnly="True" Width="*"/>  
            </DataGrid.Columns>  
        </DataGrid>  
        <Button x:Name="add_button" Content="追加" HorizontalAlignment="Left" Margin="10,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="add_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>  
        <Button x:Name="upd_button" Content="更新" HorizontalAlignment="Left" Margin="90,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="upd_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>  
        <Button x:Name="del_button" Content="削除" HorizontalAlignment="Left" Margin="170,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="del_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>  
        <Button x:Name="imp_button" Content="CSV読込" HorizontalAlignment="Left" Margin="250,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="imp_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>  
        <Button x:Name="exp_button" Content="CSV出力" HorizontalAlignment="Left" Margin="330,273,0,0" VerticalAlignment="Top" Width="75" Height="30" Click="exp_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>  
        <Button x:Name="fld_button" Content="フォルダ参照" HorizontalAlignment="Left" Margin="410,273,0,0" VerticalAlignment="Top" Width="97" Height="30" Click="fld_button_Click" Style="{DynamicResource AccentedSquareButtonStyle}"/>  
    </Grid>  
</Mah:MetroWindow>  

「性別」列を「DataGridTemplateColumn」に変更し、コンボボックスを設置。

ポイントは次のプロパティ

  • ItemsSource コンボボックスの表示内容となるリスト コードビハインドにて、DataContextに設定したリストを指定
  • DisplayMemberPath バインドされたクラスの表示するメンバーを指定
  • SelectedValuePath バインドされたクラスの値となるメンバーを指定
  • SelectedValue データグリッドにバインドされたリストのメンバーを指定 この項目が紐付きとなる

プログラムの修正

新規クラス追加

コンボボックスに設定するためのクラスを作成

Gender.cs

    using System;  
    using System.Collections.Generic;  
    using System.IO;  
    using System.Linq;  
    using System.Text;  

    namespace WpfApp1  
    {  
        /// <summary>  
        /// 性別クラス  
        /// </summary>  
        public class Gender  
        {  
            /// <summary>  
            /// コンストラクタ  
            /// </summary>  
            /// <param name="cd"></param>  
            /// <param name="name"></param>  
            public Gender(int cd, String name)  
            {  
                Cd = cd;  
                Name = name;  
            }  

            /// <summary>  
            /// 性別コード  
            /// </summary>  
            public int Cd { get; set; }  

            /// <summary>  
            /// 性別名  
            /// </summary>  
            public String Name { get; set; }  

        }  
    }  

コードビハインドの修正

下記をグローバルスコープで定義

MainWindow.xaml.cs(抜粋)

        /// <summary>  
        /// データグリッド:性別コンボの項目リスト  
        /// </summary>  
        public List<Gender> GenderList { set; get; }  

起動時にデータグリッド内のコンボボックス用リストを作成して設定

MainWindow.xaml.cs(抜粋)

            public MainWindow()  
            {  

                InitializeComponent();  

                // データグリッドに表示するコンボの項目を設定  
                GenderList = new List<Gender>();  
                GenderList.Add(new Gender(1, "&#x2642;"));  
                GenderList.Add(new Gender(2, "&#x2640;"));  
                this.DataContext = this;  

                // SampleDb.sqlite を作成(存在しなければ)  
                using (var conn = new SQLiteConnection("Data Source=SampleDb.sqlite"))  
                {  

                    // データベースに接続  
                    conn.Open();  
                    // コマンドの実行  
                    using (var command = conn.CreateCommand())  
                    {  
                        // テーブルが存在しなければ作成する  
                        // 種別マスタ  
                        StringBuilder sb = new StringBuilder();  
                        sb.Append("CREATE TABLE IF NOT EXISTS MSTKIND (");  
                        sb.Append("  KIND_CD NCHAR NOT NULL");  
                        sb.Append("  , KIND_NAME NVARCHAR");  
                        sb.Append("  , primary key (KIND_CD)");  
                        sb.Append(")");  

                        command.CommandText = sb.ToString();  
                        command.ExecuteNonQuery();  

                        // 猫テーブル  
                        sb.Clear();  
                        sb.Append("CREATE TABLE IF NOT EXISTS TBLCAT (");  
                        sb.Append("  NO INT NOT NULL");  
                        sb.Append("  , NAME NVARCHAR NOT NULL");  
                        sb.Append("  , SEX NVARCHAR NOT NULL");  
                        sb.Append("  , AGE INT DEFAULT 0 NOT NULL");  
                        sb.Append("  , KIND_CD NCHAR DEFAULT 0 NOT NULL");  
                        sb.Append("  , FAVORITE NVARCHAR");  
                        sb.Append("  , primary key (NO)");  
                        sb.Append(")");  

                        command.CommandText = sb.ToString();  
                        command.ExecuteNonQuery();  

                    }  

                    // 種別マスタを取得してコンボボックスに設定する  
                    using (DataContext con = new DataContext(conn))  
                    {  
                        // データを取得  
                        Table<Kind> tblCat = con.GetTable<Kind>();  
                        IQueryable<Kind> result = from x in tblCat orderby x.KindCd select x;  

                        // 最初の要素は「指定なし」とする  
                        Kind empty = new Kind();  
                        empty.KindCd = "";  
                        empty.KindName = "指定なし";  
                        var list = result.ToList();  
                        list.Insert(0, empty);  

                        // コンボボックスに設定  
                        this.search_kind.ItemsSource = list;  
                        this.search_kind.DisplayMemberPath = "KindName";  
                    }  
                    // 切断  
                    conn.Close();  
                }  
            }  

起動してみる

起動直後、「性別」がコンボボックスになってますね。

クリックすると、コンボボックスが展開されて変更することができます。

まとめ

データグリッドにコンボボックスを表示する方法は色々ありますが、
とりあえずこんな感じで落ち着きました。

今後他のコントロールも試していきたいと思います。

ではでは。

記事が少しでもいいなと思ったらクラップを送ってみよう!
5
+1
@doraxdoraの技術ブログ 主に Java, C#, Python, Javascript の記事を載せていく予定。

よく一緒に読まれている記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる

技術ブログをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

技術ブログを開設する

Qrunchでアウトプットをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

Markdownで書ける

ログ機能でアウトプットを加速

デザインのカスタマイズが可能

技術ブログ開設

ここから先はアカウント(ブログ)開設が必要です

英数字4文字以上
.qrunch.io
英数字6文字以上
ログインする