Create DataGridTemplateColumn Through C# Code

Eric R. picture Eric R. · Jan 8, 2012 · Viewed 15.6k times · Source

I have a dynamic Datagrid that I have created. I am creating each column for it through code behind. I am having troubles on a column that I want to be displayed at a textblock when not editing, but as a combobox while editing. I have an ObservableCollection of Transactions. Each Transaction has a type called "Account". Here is what I have so far:

    private DataGridTemplateColumn GetAccountColumn()
    {
        // Create The Column
        DataGridTemplateColumn accountColumn = new DataGridTemplateColumn();
        accountColumn.Header = "Account";

        Binding bind = new Binding("Account");
        bind.Mode = BindingMode.TwoWay;

        // Create the TextBlock
        FrameworkElementFactory textFactory = new FrameworkElementFactory(typeof(TextBlock));
        textFactory.SetBinding(TextBlock.TextProperty, bind);
        DataTemplate textTemplate = new DataTemplate();
        textTemplate.VisualTree = textFactory;

        // Create the ComboBox
        bind.Mode = BindingMode.OneWay;
        FrameworkElementFactory comboFactory = new FrameworkElementFactory(typeof(ComboBox));
        comboFactory.SetValue(ComboBox.DataContextProperty, this.Transactions);
        comboFactory.SetValue(ComboBox.IsTextSearchEnabledProperty, true);
        comboFactory.SetBinding(ComboBox.ItemsSourceProperty, bind);

        DataTemplate comboTemplate = new DataTemplate();
        comboTemplate.VisualTree = comboFactory;

        // Set the Templates to the Column
        accountColumn.CellTemplate = textTemplate;
        accountColumn.CellEditingTemplate = comboTemplate;

        return accountColumn;
    }

The value displays in the TextBlock. However, in the combobox, I am only getting one character to display per item. For example, here is the textblock:

enter image description here

But when I click to edit and go into the combobox, here is what is shown:

enter image description here

Can someone help me out so that the items in the Combobox are displayed properly? Also, when I select something from the Combobox, the textblock isn't updated with the item I selected.

UPDATED:

Here is my column as of now. The items in the ComboBox are being displayed properly. The issue now is that when a new item is selected, the text in the TextBlock isn't updated with the new item.

    private DataGridTemplateColumn GetAccountColumn()
    {
        // Create The Column
        DataGridTemplateColumn accountColumn = new DataGridTemplateColumn();
        accountColumn.Header = "Account";

        Binding bind = new Binding("Account");
        bind.Mode = BindingMode.OneWay;

        // Create the TextBlock
        FrameworkElementFactory textFactory = new FrameworkElementFactory(typeof(TextBlock));
        textFactory.SetBinding(TextBlock.TextProperty, bind);
        DataTemplate textTemplate = new DataTemplate();
        textTemplate.VisualTree = textFactory;

        // Create the ComboBox
        Binding comboBind = new Binding("Account");
        comboBind.Mode = BindingMode.OneWay;

        FrameworkElementFactory comboFactory = new FrameworkElementFactory(typeof(ComboBox));
        comboFactory.SetValue(ComboBox.IsTextSearchEnabledProperty, true);
        comboFactory.SetValue(ComboBox.ItemsSourceProperty, this.Accounts);
        comboFactory.SetBinding(ComboBox.SelectedItemProperty, comboBind);

        DataTemplate comboTemplate = new DataTemplate();
        comboTemplate.VisualTree = comboFactory;

        // Set the Templates to the Column
        accountColumn.CellTemplate = textTemplate;
        accountColumn.CellEditingTemplate = comboTemplate;

        return accountColumn;
    }

The "Accounts" property is declared like this in my MainWindow class:

public ObservableCollection<string> Accounts { get; set; }

    public MainWindow()
    {
        this.Types = new ObservableCollection<string>();
        this.Parents = new ObservableCollection<string>();
        this.Transactions = new ObservableCollection<Transaction>();
        this.Accounts = new ObservableCollection<string>();

        OpenDatabase();
        InitializeComponent();
    }

Here is my Transaction Class:

public class Transaction
{
    private string date;
    private string number;
    private string account;

    public string Date
    {
        get { return date; }
        set { date = value; }
    }

    public string Number
    {
        get { return number; }
        set { number = value; }
    }

    public string Account
    {
        get { return account; }
        set { account = value; }
    }
}

Answer

H.B. picture H.B. · Jan 8, 2012

You bind the ItemsSource to the selected value, a string, aka char array, so every character is used as an item, the ItemsSource binding presumably should target some other collection from which the value can be chosen.