Create DataGridTemplateColumn Through C# Code
Solution 1
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.
Solution 2
Dim newBind As Binding = New Binding("LinktoCommonOutputBus")
newBind.Mode = BindingMode.OneWay
factory1.SetValue(ComboBox.ItemsSourceProperty, dictionary)
factory1.SetValue(ComboBox.NameProperty, name)
factory1.SetValue(ComboBox.SelectedValuePathProperty, "Key")
factory1.SetValue(ComboBox.DisplayMemberPathProperty, "Value")
factory1.SetBinding(ComboBox.SelectedValueProperty, newBind)
By creating Binding you can set SelectedValue in a datagrid for WPF.
Eric R.
Updated on June 05, 2022Comments
-
Eric R. almost 2 years
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:
But when I click to edit and go into the combobox, here is what is shown:
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; } } }
-
Eric R. over 12 yearsAhhh yes that makes sense! Thanks for the info! I added code so that the itemssource comes from a different collection now. The items in the combobox appear as they should. One more thing though, when I select a different value from the combobox, the textblock isn't updated with the new item. How would I fix that?
-
H.B. over 12 years@EricR.: Bind the
SelectedItem
orSelectedValue
toAccount
. UseSelectedItem
if the items are already the strings that should be used as value for account, useSelectedValue
in combination withSelectedValuePath
if the value is a property on the selected item (and not the item itself). -
Eric R. over 12 yearsHow would I do that? The new collection for Accounts that I am using is an ObservableCollection<string>. I am setting the ItemsSource now by this: comboFactory.SetValue(ComboBox.ItemsSourceProperty, this.Accounts);. this.Accounts is the ObservableCollection. So how would I set the SelectedItem for that? I really appreciate all the help you have given me so far!
-
H.B. over 12 years@EricR.: Create a new
Binding
with the path"Account"
and use SetBinding to set it on theSelectedItemProperty
, that should be all you need to do... -
Eric R. over 12 yearsYes, I have added this in. The value still isn't displayed in the TextBlock after choosing it.
-
H.B. over 12 years@EricR.: Did you confirm the change using return? In a DataGrid edits normally need to be confirmed before they affect the item. Speaking of which, the DataGridComboBoxColumn should already do exactly what you appear to want: Display the value and show a combo-box when editing.
-
Eric R. over 12 yearsI have edited my question to show what my current function looks like to create the column. Let me know your thoughts since the TextBlock still isn't updating when a new item is selected.
-
H.B. over 12 years@EricR.: Obviously the binding on the
SelectedItem
needs to beTwoWay
, i never said you should change it toOneWay
which makes it unable to change theAccount
property. -
Eric R. over 12 yearsI know you never said that. I added that in as part of my testing because when I have the mode set to TwoWay, I get the following error: A TwoWay or OneWayToSource binding cannot work on the read-only property 'Account' of type 'System.Data.DataRowView'.
-
H.B. over 12 years@EricR.: That means your data item which owns the account property does not allow you to change it in the first place, so the whole combobox is rather pointless.
-
Eric R. over 12 yearsI am confused about what to do next. It is not my intention to have this as a readonly property. I edited my response again to show how I declare my property. All is done in my MainWindow class.
-
H.B. over 12 years@EricR.: The problem is the
Transaction.Account
property, all that other stuff seems fine. What does the transaction class look like? -
Eric R. over 12 yearsI updated above again to show my Transaction class. I am creating the Account Property the same way as my other properties. It is just a string basically.
-
Eric R. over 12 yearsI figured it out. I was loading my datagrid initially from an SQL query on my Database. The query was performing an inner join to get the value for the Account Column. Apparently this set the column on my DataTable to readonly. Took me awhile to track that one down. So now I just set the readonly property to false and I can use my ComboBox to change it and the text displays in my TextBlock. Thanks so much for all your help!