none
DataGridTemplateColumnをXAMLを使わずにコントロールを設定する方法 RRS feed

  • 質問

  • <DataGridTemplateColumn Header="test">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <Button Content="ボタン" Name="DataGridButton" Width="50" Height="20"/>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>

    C#上でDataGridTemplateColumnを使いたいですが、DataGridTemplateColumnはDataTemplateでコントロールを設定されることを前提に作られているような気がしてます。また調べたところDataTemplateはXAMLでないと使うのは難しいようです。

    もし、C#上でDataGridに任意のSystem.Windows.Controlsを配置したい場合、方法ありますか。


    • 編集済み 星 睦美 2014年3月14日 4:47 axml ->XAML
    • 移動 星 睦美 2014年3月14日 4:58 Visual C# から
    2014年3月14日 1:53

回答

  • DataGridBoundColumnを使った方が楽かもね

    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Data;
    using System.Windows.Media;
    namespace WpfApplication1
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
    
                DataTable table1 = new DataTable();
                table1.Columns.Add("ID", typeof(int));
                table1.Columns.Add("Name", typeof(string));
                table1.Columns.Add("Value", typeof(int));
                table1.Columns.Add("Flag", typeof(bool));
                table1.Columns.Add("Date", typeof(DateTime));
                table1.Columns.Add("Enum", typeof(System.DateTimeKind));
                table1.PrimaryKey = new DataColumn[] { table1.Columns[0] };
    
                table1.Rows.Add(1, "ABC", 1, true, DateTime.Now.Date, DateTimeKind.Local);
                table1.Rows.Add(2, "あいうえ", 2, false, DateTime.Now.Date.AddDays(1), DateTimeKind.Utc);
    
                DataGrid dg = new DataGrid();
    
                if (false)
                {   //自動生成の場合
                    dg.AutoGeneratingColumn += new EventHandler<DataGridAutoGeneratingColumnEventArgs>(dg_AutoGeneratingColumn);
                }
                else
                {
                    //明示的生成の場合
                    dg.AutoGenerateColumns=false;
                    foreach (DataColumn clm in table1.Columns)
                    {
                        dg.Columns.Add(CreateColumn(clm.ColumnName , clm.DataType));
                    }
                }
    
                dg.ItemsSource = table1.DefaultView;
                this.Content = dg;
            }
    
            void dg_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
            {   //DataGridで列が生成されるときに呼ばれる
                e.Column= CreateColumn(e.PropertyName, e.PropertyType);
            }
    
            private DataGridColumn CreateColumn(string columnName, Type columnBindingType)
            {
                if (columnName == "ID")
                {
                    //ID列はForms.NumericUpdownを使ってみる
                    var frmclm = new DataGridFormsColumn<System.Windows.Forms.NumericUpDown>();
                    frmclm.Binding = new Binding(columnName);
                    frmclm.Generate += (s2, e2) =>
                    {
                        System.Windows.Forms.NumericUpDown num
                        = (System.Windows.Forms.NumericUpDown)e2.Control;
                        num.Maximum = int.MaxValue;
                        num.Value = (int)(e2.Value ?? 1);
                        num.ValueChanged += (s3, e3) =>
                        {
                            e2.Setter((int)num.Value);
                        };
                    };
                    return  frmclm;
                }
                else
                {
                    //列の型に応じて編集コントロールを変更してみる
                    var clm = new DataGridCustomColumn();
                    clm.Header = columnName;
                    clm.Binding = new Binding(columnName);
                    if (columnBindingType == typeof(int))
                    {
                        clm.EditType = EditType.Slider;
                    }
                    else if (columnBindingType == typeof(string))
                    {
                        clm.EditType = EditType.TextBox;
                    }
                    else if (columnBindingType == typeof(bool))
                    {
                        clm.EditType = EditType.CheckBox;
                    }
                    else if (columnBindingType == typeof(DateTime))
                    {
                        clm.EditType = EditType.DatePicker;
                        clm.Binding.StringFormat = "yyyy/MM/dd";
                    }
                    else if (columnBindingType.IsEnum)
                    {
                        clm.EditType = EditType.ComboBox;
                        clm.ItemsSource = Enum.GetValues(columnBindingType);
                    }
                    return clm;
                }
            }
        }
    
        public enum EditType
        {
            None, TextBox, Slider, CheckBox, DatePicker, ComboBox
        }
        /// <summary>編集時のコントロールを選べるDataGridColumn</summary>
        class DataGridCustomColumn : System.Windows.Controls.DataGridBoundColumn
        {
            public EditType EditType { get; set; }
    
            public System.Collections.IEnumerable ItemsSource
            {
                get { return (System.Collections.IEnumerable)GetValue(ItemsSourceProperty); }
                set { SetValue(ItemsSourceProperty, value); }
            }
            //ComboBox列の場合のItemsSource
            public static readonly DependencyProperty ItemsSourceProperty =
                DependencyProperty.Register
                ("ItemsSource", typeof(System.Collections.IEnumerable), typeof(DataGridCustomColumn)
                , new UIPropertyMetadata(default(System.Collections.IEnumerable)));
    
            protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
            {
                switch (this.EditType)
                {
                case EditType.TextBox:
                    TextBox textBox = new TextBox();
                    textBox.SetBinding(TextBox.TextProperty, this.Binding);
                    return textBox;
    
                case EditType.Slider:
                    Slider slider = new Slider();
                    slider.SetBinding(Slider.ValueProperty, this.Binding);
                    return slider;
    
                case EditType.CheckBox:
                    CheckBox chk = new CheckBox();
                    chk.SetBinding(CheckBox.IsCheckedProperty, this.Binding);
                    return chk;
    
                case EditType.DatePicker:
                    DatePicker picker = new DatePicker();
                    picker.SetBinding(DatePicker.SelectedDateProperty, this.Binding);
                    return picker;
    
                case EditType.ComboBox:
                    ComboBox combo = new ComboBox();
                    combo.ItemsSource = this.ItemsSource;
                    combo.SetBinding(ComboBox.SelectedValueProperty, this.Binding);
                    return combo;
    
                default:
                    TextBlock block = new TextBlock();
                    block.SetBinding(TextBlock.TextProperty, this.Binding);
                    return block;
                }
            }
    
            protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
            {
                TextBlock textBlock = new TextBlock();
                textBlock.SetBinding(TextBlock.TextProperty, this.Binding);
                return textBlock;
            }
        }
    
        /// <summary>編集時にForms.Controlを使うDataGridColumn</summary>
        /// <typeparam name="T">使うForms.Controlの型</typeparam>
        /// <remarks>System.Windows.Forms.dllとWindowsFormsIntegration.dllを参照</remarks>
        class DataGridFormsColumn<T> : System.Windows.Controls.DataGridBoundColumn where T : System.Windows.Forms.Control
        {
            protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
            {
                var control = Activator.CreateInstance<T>();
                WindowsFormsHostEx host = new WindowsFormsHostEx();
                host.SetBinding(WindowsFormsHostEx.ValueProperty, this.Binding);
                host.Child = control;
                var g = Generate;
                if (g != null)
                {
                    TextBlock block = (TextBlock)cell.Content;
                    g(this, new DataGridFormsEventArgs(control, block.Tag, (Action<object>)host.Setter));
                }
    
                return host;
            }
    
            protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
            {
                TextBlock textBlock = new TextBlock();
                textBlock.SetBinding(TextBlock.TextProperty, this.Binding);
                textBlock.SetBinding(TextBlock.TagProperty, this.Binding);
                return textBlock;
            }
    
            /// <summary>Forms.Controlが生成されるときに呼ばれる </summary>
            public event EventHandler<DataGridFormsEventArgs> Generate;
    
            public class DataGridFormsEventArgs : EventArgs
            {
                public DataGridFormsEventArgs(System.Windows.Forms.Control ctl, object value, Action<object> setter)
                {
                    this.Control = ctl;
                    this.Value = value;
                    this.Setter = setter;
                }
                /// <summary> 生成されたForms.Control </summary>
                public System.Windows.Forms.Control Control { get; private set; }
                /// <summary>開始時の値</summary>
                public object Value { get; private set; }
                /// <summary>Forms.Controlで変更した値を反映するためのデリゲート</summary>
                public Action<object> Setter { get; private set; }
            }
    
            class WindowsFormsHostEx : System.Windows.Forms.Integration.WindowsFormsHost
            {
                /// <summary>編集値の中継用</summary>
                public object Value
                {
                    get { return (object)GetValue(ValueProperty); }
                    set { SetValue(ValueProperty, value); }
                }
                public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(object), typeof(WindowsFormsHostEx), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
    
                public void Setter(object value)
                {
                    this.Value = value;
                }
            }
        }
    }


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    2014年3月16日 16:20

すべての返信

  • なぜWPFの開発でC#のコーディングに拘られるのでしょうか?またこういう記事もあります。

    XAML Tricks – C#じゃできなくてXAMLだからできる事


    ひらぽん http://d.hatena.ne.jp/hilapon/

    2014年3月14日 2:02
    モデレータ
  • DataGridで使いたいコントロールがデータベースから引っ張ってきた列によってコンボボックスやチェックボックスやスライダーバーと変動するためです。 また列も変動します。 xamlで可能ですか。
    2014年3月14日 4:33
  • ちょっとやりたいことの詳細がわかりませんが、XAMLでBindingしてやれば複数のコントロールと連携は可能です。またそうなればバインド用のViewModelも合った方が便利かと思います。

    ひらぽん http://d.hatena.ne.jp/hilapon/


    2014年3月14日 4:40
    モデレータ
  • AXML上でDtaGrid____Columnの雛形を作れて、コード上でちょっとカスタマイズしてDataGrid.Clumns.Addできませんか。

    データーベースからDataGridにバインドします。その際、行が多いので1行1行コードするのが大変ですし、列名が変更されるとヘッダー名も変わります。列名に対する表示する列挙型を持っていて、列名に対応したコントロールをDataGridにバインドする際に決めたいです。

    こうするとすべてデータベース依存で表示されるコントロールが決まるので。

    2014年3月14日 9:25
  • DataGridBoundColumnを使った方が楽かもね

    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Data;
    using System.Windows.Media;
    namespace WpfApplication1
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
    
                DataTable table1 = new DataTable();
                table1.Columns.Add("ID", typeof(int));
                table1.Columns.Add("Name", typeof(string));
                table1.Columns.Add("Value", typeof(int));
                table1.Columns.Add("Flag", typeof(bool));
                table1.Columns.Add("Date", typeof(DateTime));
                table1.Columns.Add("Enum", typeof(System.DateTimeKind));
                table1.PrimaryKey = new DataColumn[] { table1.Columns[0] };
    
                table1.Rows.Add(1, "ABC", 1, true, DateTime.Now.Date, DateTimeKind.Local);
                table1.Rows.Add(2, "あいうえ", 2, false, DateTime.Now.Date.AddDays(1), DateTimeKind.Utc);
    
                DataGrid dg = new DataGrid();
    
                if (false)
                {   //自動生成の場合
                    dg.AutoGeneratingColumn += new EventHandler<DataGridAutoGeneratingColumnEventArgs>(dg_AutoGeneratingColumn);
                }
                else
                {
                    //明示的生成の場合
                    dg.AutoGenerateColumns=false;
                    foreach (DataColumn clm in table1.Columns)
                    {
                        dg.Columns.Add(CreateColumn(clm.ColumnName , clm.DataType));
                    }
                }
    
                dg.ItemsSource = table1.DefaultView;
                this.Content = dg;
            }
    
            void dg_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
            {   //DataGridで列が生成されるときに呼ばれる
                e.Column= CreateColumn(e.PropertyName, e.PropertyType);
            }
    
            private DataGridColumn CreateColumn(string columnName, Type columnBindingType)
            {
                if (columnName == "ID")
                {
                    //ID列はForms.NumericUpdownを使ってみる
                    var frmclm = new DataGridFormsColumn<System.Windows.Forms.NumericUpDown>();
                    frmclm.Binding = new Binding(columnName);
                    frmclm.Generate += (s2, e2) =>
                    {
                        System.Windows.Forms.NumericUpDown num
                        = (System.Windows.Forms.NumericUpDown)e2.Control;
                        num.Maximum = int.MaxValue;
                        num.Value = (int)(e2.Value ?? 1);
                        num.ValueChanged += (s3, e3) =>
                        {
                            e2.Setter((int)num.Value);
                        };
                    };
                    return  frmclm;
                }
                else
                {
                    //列の型に応じて編集コントロールを変更してみる
                    var clm = new DataGridCustomColumn();
                    clm.Header = columnName;
                    clm.Binding = new Binding(columnName);
                    if (columnBindingType == typeof(int))
                    {
                        clm.EditType = EditType.Slider;
                    }
                    else if (columnBindingType == typeof(string))
                    {
                        clm.EditType = EditType.TextBox;
                    }
                    else if (columnBindingType == typeof(bool))
                    {
                        clm.EditType = EditType.CheckBox;
                    }
                    else if (columnBindingType == typeof(DateTime))
                    {
                        clm.EditType = EditType.DatePicker;
                        clm.Binding.StringFormat = "yyyy/MM/dd";
                    }
                    else if (columnBindingType.IsEnum)
                    {
                        clm.EditType = EditType.ComboBox;
                        clm.ItemsSource = Enum.GetValues(columnBindingType);
                    }
                    return clm;
                }
            }
        }
    
        public enum EditType
        {
            None, TextBox, Slider, CheckBox, DatePicker, ComboBox
        }
        /// <summary>編集時のコントロールを選べるDataGridColumn</summary>
        class DataGridCustomColumn : System.Windows.Controls.DataGridBoundColumn
        {
            public EditType EditType { get; set; }
    
            public System.Collections.IEnumerable ItemsSource
            {
                get { return (System.Collections.IEnumerable)GetValue(ItemsSourceProperty); }
                set { SetValue(ItemsSourceProperty, value); }
            }
            //ComboBox列の場合のItemsSource
            public static readonly DependencyProperty ItemsSourceProperty =
                DependencyProperty.Register
                ("ItemsSource", typeof(System.Collections.IEnumerable), typeof(DataGridCustomColumn)
                , new UIPropertyMetadata(default(System.Collections.IEnumerable)));
    
            protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
            {
                switch (this.EditType)
                {
                case EditType.TextBox:
                    TextBox textBox = new TextBox();
                    textBox.SetBinding(TextBox.TextProperty, this.Binding);
                    return textBox;
    
                case EditType.Slider:
                    Slider slider = new Slider();
                    slider.SetBinding(Slider.ValueProperty, this.Binding);
                    return slider;
    
                case EditType.CheckBox:
                    CheckBox chk = new CheckBox();
                    chk.SetBinding(CheckBox.IsCheckedProperty, this.Binding);
                    return chk;
    
                case EditType.DatePicker:
                    DatePicker picker = new DatePicker();
                    picker.SetBinding(DatePicker.SelectedDateProperty, this.Binding);
                    return picker;
    
                case EditType.ComboBox:
                    ComboBox combo = new ComboBox();
                    combo.ItemsSource = this.ItemsSource;
                    combo.SetBinding(ComboBox.SelectedValueProperty, this.Binding);
                    return combo;
    
                default:
                    TextBlock block = new TextBlock();
                    block.SetBinding(TextBlock.TextProperty, this.Binding);
                    return block;
                }
            }
    
            protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
            {
                TextBlock textBlock = new TextBlock();
                textBlock.SetBinding(TextBlock.TextProperty, this.Binding);
                return textBlock;
            }
        }
    
        /// <summary>編集時にForms.Controlを使うDataGridColumn</summary>
        /// <typeparam name="T">使うForms.Controlの型</typeparam>
        /// <remarks>System.Windows.Forms.dllとWindowsFormsIntegration.dllを参照</remarks>
        class DataGridFormsColumn<T> : System.Windows.Controls.DataGridBoundColumn where T : System.Windows.Forms.Control
        {
            protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
            {
                var control = Activator.CreateInstance<T>();
                WindowsFormsHostEx host = new WindowsFormsHostEx();
                host.SetBinding(WindowsFormsHostEx.ValueProperty, this.Binding);
                host.Child = control;
                var g = Generate;
                if (g != null)
                {
                    TextBlock block = (TextBlock)cell.Content;
                    g(this, new DataGridFormsEventArgs(control, block.Tag, (Action<object>)host.Setter));
                }
    
                return host;
            }
    
            protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
            {
                TextBlock textBlock = new TextBlock();
                textBlock.SetBinding(TextBlock.TextProperty, this.Binding);
                textBlock.SetBinding(TextBlock.TagProperty, this.Binding);
                return textBlock;
            }
    
            /// <summary>Forms.Controlが生成されるときに呼ばれる </summary>
            public event EventHandler<DataGridFormsEventArgs> Generate;
    
            public class DataGridFormsEventArgs : EventArgs
            {
                public DataGridFormsEventArgs(System.Windows.Forms.Control ctl, object value, Action<object> setter)
                {
                    this.Control = ctl;
                    this.Value = value;
                    this.Setter = setter;
                }
                /// <summary> 生成されたForms.Control </summary>
                public System.Windows.Forms.Control Control { get; private set; }
                /// <summary>開始時の値</summary>
                public object Value { get; private set; }
                /// <summary>Forms.Controlで変更した値を反映するためのデリゲート</summary>
                public Action<object> Setter { get; private set; }
            }
    
            class WindowsFormsHostEx : System.Windows.Forms.Integration.WindowsFormsHost
            {
                /// <summary>編集値の中継用</summary>
                public object Value
                {
                    get { return (object)GetValue(ValueProperty); }
                    set { SetValue(ValueProperty, value); }
                }
                public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(object), typeof(WindowsFormsHostEx), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
    
                public void Setter(object value)
                {
                    this.Value = value;
                }
            }
        }
    }


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    2014年3月16日 16:20
  • DataGridBoundColumnを使った方が楽かもね

    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Data;
    using System.Windows.Media;
    namespace WpfApplication1
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
    
                DataTable table1 = new DataTable();
                table1.Columns.Add("ID", typeof(int));
                table1.Columns.Add("Name", typeof(string));
                table1.Columns.Add("Value", typeof(int));
                table1.Columns.Add("Flag", typeof(bool));
                table1.Columns.Add("Date", typeof(DateTime));
                table1.Columns.Add("Enum", typeof(System.DateTimeKind));
                table1.PrimaryKey = new DataColumn[] { table1.Columns[0] };
    
                table1.Rows.Add(1, "ABC", 1, true, DateTime.Now.Date, DateTimeKind.Local);
                table1.Rows.Add(2, "あいうえ", 2, false, DateTime.Now.Date.AddDays(1), DateTimeKind.Utc);
    
                DataGrid dg = new DataGrid();
    
                if (false)
                {   //自動生成の場合
                    dg.AutoGeneratingColumn += new EventHandler<DataGridAutoGeneratingColumnEventArgs>(dg_AutoGeneratingColumn);
                }
                else
                {
                    //明示的生成の場合
                    dg.AutoGenerateColumns=false;
                    foreach (DataColumn clm in table1.Columns)
                    {
                        dg.Columns.Add(CreateColumn(clm.ColumnName , clm.DataType));
                    }
                }
    
                dg.ItemsSource = table1.DefaultView;
                this.Content = dg;
            }
    
            void dg_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
            {   //DataGridで列が生成されるときに呼ばれる
                e.Column= CreateColumn(e.PropertyName, e.PropertyType);
            }
    
            private DataGridColumn CreateColumn(string columnName, Type columnBindingType)
            {
                if (columnName == "ID")
                {
                    //ID列はForms.NumericUpdownを使ってみる
                    var frmclm = new DataGridFormsColumn<System.Windows.Forms.NumericUpDown>();
                    frmclm.Binding = new Binding(columnName);
                    frmclm.Generate += (s2, e2) =>
                    {
                        System.Windows.Forms.NumericUpDown num
                        = (System.Windows.Forms.NumericUpDown)e2.Control;
                        num.Maximum = int.MaxValue;
                        num.Value = (int)(e2.Value ?? 1);
                        num.ValueChanged += (s3, e3) =>
                        {
                            e2.Setter((int)num.Value);
                        };
                    };
                    return  frmclm;
                }
                else
                {
                    //列の型に応じて編集コントロールを変更してみる
                    var clm = new DataGridCustomColumn();
                    clm.Header = columnName;
                    clm.Binding = new Binding(columnName);
                    if (columnBindingType == typeof(int))
                    {
                        clm.EditType = EditType.Slider;
                    }
                    else if (columnBindingType == typeof(string))
                    {
                        clm.EditType = EditType.TextBox;
                    }
                    else if (columnBindingType == typeof(bool))
                    {
                        clm.EditType = EditType.CheckBox;
                    }
                    else if (columnBindingType == typeof(DateTime))
                    {
                        clm.EditType = EditType.DatePicker;
                        clm.Binding.StringFormat = "yyyy/MM/dd";
                    }
                    else if (columnBindingType.IsEnum)
                    {
                        clm.EditType = EditType.ComboBox;
                        clm.ItemsSource = Enum.GetValues(columnBindingType);
                    }
                    return clm;
                }
            }
        }
    
        public enum EditType
        {
            None, TextBox, Slider, CheckBox, DatePicker, ComboBox
        }
        /// <summary>編集時のコントロールを選べるDataGridColumn</summary>
        class DataGridCustomColumn : System.Windows.Controls.DataGridBoundColumn
        {
            public EditType EditType { get; set; }
    
            public System.Collections.IEnumerable ItemsSource
            {
                get { return (System.Collections.IEnumerable)GetValue(ItemsSourceProperty); }
                set { SetValue(ItemsSourceProperty, value); }
            }
            //ComboBox列の場合のItemsSource
            public static readonly DependencyProperty ItemsSourceProperty =
                DependencyProperty.Register
                ("ItemsSource", typeof(System.Collections.IEnumerable), typeof(DataGridCustomColumn)
                , new UIPropertyMetadata(default(System.Collections.IEnumerable)));
    
            protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
            {
                switch (this.EditType)
                {
                case EditType.TextBox:
                    TextBox textBox = new TextBox();
                    textBox.SetBinding(TextBox.TextProperty, this.Binding);
                    return textBox;
    
                case EditType.Slider:
                    Slider slider = new Slider();
                    slider.SetBinding(Slider.ValueProperty, this.Binding);
                    return slider;
    
                case EditType.CheckBox:
                    CheckBox chk = new CheckBox();
                    chk.SetBinding(CheckBox.IsCheckedProperty, this.Binding);
                    return chk;
    
                case EditType.DatePicker:
                    DatePicker picker = new DatePicker();
                    picker.SetBinding(DatePicker.SelectedDateProperty, this.Binding);
                    return picker;
    
                case EditType.ComboBox:
                    ComboBox combo = new ComboBox();
                    combo.ItemsSource = this.ItemsSource;
                    combo.SetBinding(ComboBox.SelectedValueProperty, this.Binding);
                    return combo;
    
                default:
                    TextBlock block = new TextBlock();
                    block.SetBinding(TextBlock.TextProperty, this.Binding);
                    return block;
                }
            }
    
            protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
            {
                TextBlock textBlock = new TextBlock();
                textBlock.SetBinding(TextBlock.TextProperty, this.Binding);
                return textBlock;
            }
        }
    
        /// <summary>編集時にForms.Controlを使うDataGridColumn</summary>
        /// <typeparam name="T">使うForms.Controlの型</typeparam>
        /// <remarks>System.Windows.Forms.dllとWindowsFormsIntegration.dllを参照</remarks>
        class DataGridFormsColumn<T> : System.Windows.Controls.DataGridBoundColumn where T : System.Windows.Forms.Control
        {
            protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
            {
                var control = Activator.CreateInstance<T>();
                WindowsFormsHostEx host = new WindowsFormsHostEx();
                host.SetBinding(WindowsFormsHostEx.ValueProperty, this.Binding);
                host.Child = control;
                var g = Generate;
                if (g != null)
                {
                    TextBlock block = (TextBlock)cell.Content;
                    g(this, new DataGridFormsEventArgs(control, block.Tag, (Action<object>)host.Setter));
                }
    
                return host;
            }
    
            protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
            {
                TextBlock textBlock = new TextBlock();
                textBlock.SetBinding(TextBlock.TextProperty, this.Binding);
                textBlock.SetBinding(TextBlock.TagProperty, this.Binding);
                return textBlock;
            }
    
            /// <summary>Forms.Controlが生成されるときに呼ばれる </summary>
            public event EventHandler<DataGridFormsEventArgs> Generate;
    
            public class DataGridFormsEventArgs : EventArgs
            {
                public DataGridFormsEventArgs(System.Windows.Forms.Control ctl, object value, Action<object> setter)
                {
                    this.Control = ctl;
                    this.Value = value;
                    this.Setter = setter;
                }
                /// <summary> 生成されたForms.Control </summary>
                public System.Windows.Forms.Control Control { get; private set; }
                /// <summary>開始時の値</summary>
                public object Value { get; private set; }
                /// <summary>Forms.Controlで変更した値を反映するためのデリゲート</summary>
                public Action<object> Setter { get; private set; }
            }
    
            class WindowsFormsHostEx : System.Windows.Forms.Integration.WindowsFormsHost
            {
                /// <summary>編集値の中継用</summary>
                public object Value
                {
                    get { return (object)GetValue(ValueProperty); }
                    set { SetValue(ValueProperty, value); }
                }
                public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(object), typeof(WindowsFormsHostEx), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
    
                public void Setter(object value)
                {
                    this.Value = value;
                }
            }
        }
    }


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    DataGridBoundColumnを使うととても柔軟なものが作れるのですね。

    とても勉強になります。ありがとうございます。

    comboxがenumでなくDataRowCollectionにしたい場合、表示を調節しないといけないので以下のようにしたものの苦し紛れ感が出ておりスマートな方法ありませんか^^;

    {
    //略
    //  コンボボックスにはDataRowCollectionをバインドしている
    case EditType.ComboBox:
                    ComboBox combo = new ComboBox();
                    combo.ItemsSource = this.ItemsSource;
                    combo.SetBinding(ComboBox.SelectedValueProperty, this.Binding);
                    combo.SelectedValuePath = this.SelectedValuePath;
                    combo.DisplayMemberPath = this.DisplayMemberPath;
                    return combo;
    //略
    }
            protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
            {
                TextBlock textBlock = new TextBlock();
                if (this.EditType == EditType.ComboBox)
                {
                    var vm = (DataRowCollection)this.ItemsSource;
                    if (dataItem.GetType() == typeof(DataRowView))
                    {
                        var item = ((DataRowView)dataItem);
                        var di = item.Row[DisplayIndex];
                        if (di is IConvertible)
                        {
                            int idx = ((IConvertible)di).ToInt32(null);
                            for (int i = 0; i < vm.Count; i++)
                            {
                                var ary = vm[i].ItemArray;//ary[0]がkey,ary[1]がvalue
                                if (idx == ((IConvertible)ary[0]).ToInt32(null))
                                {
                                    textBlock.SetCurrentValue(TextBlock.TextProperty, ary[1]);
                                    break;
                                }
                            }
    
                        }
                    }
                }
                else
                 textBlock.SetBinding(TextBlock.TextProperty, this.Binding);
                return textBlock;
            }

    2014年3月18日 2:09