Binding ItemsSource at runtime to ObservableCollection<T>

Nov 20, 2008 at 2:00 AM
I need to bind the ItemsSource of  a DataGridComboBoxColumn to an ObservableCollection<T> (or potentially another list type) that will be populated at runtime using a LINQ query.  What is the XAML?  Below is one try that *doesn't* work.  

    <toolkit:DataGridComboBoxColumn Header="Customer02" MinWidth="200"
                    SelectedItemBinding="{Binding Path=Customer, Mode=TwoWay,
                    UpdateSourceTrigger=PropertyChanged}"
     ItemsSource="{Binding Path=_customers}"
                    Width="SizeToCells"
                    CanUserSort="True" >
    </toolkit:DataGridComboBoxColumn>

Notes:

1. The grid rows are Orders.
2. "Customer" is the property to which I want to bind the SelectedItem of the ComboBox. Customer is a related object, of type Customer.
3. "_customers" is the name of the ObservableCollection<Customer> in the UserControl's C# code.

Thanks!
Nov 20, 2008 at 8:08 AM
Hi,

You can only bind to dependency properties on dependency objects, or CLR properties. A field on your code-behind partial class is neither of these!

There are a few ways you could approach this, the most common are probably:

1. Simple set the ItemsSource in the code behind, i.e. if you name your DataGridComboBoxColumn Name="MyComboColumn", you can simple do the following in your code-behind:

MyComboColumn.ItemsSource=_customer;

You do not have to do everything in XAML!

2. Use an ObjectDataProvider. You can find an example of this in a recent article I published on codeproject

http://www.codeproject.com/KB/WPF/WPFDataGridExamples.aspx#dataset





Colin E.
Nov 20, 2008 at 6:04 PM

Thank you, Colin.

The DataGridComboBoxColumn doesn't seem to have a Name property (by that name or any other); but I am able to assign the ItemsSource in code behind using the column indexer


            DataGridComboBoxColumn dgCbCol = (DataGridComboBoxColumn)_ordersDataGrid.Columns[2];
            dgCbCol.ItemsSource = _customers;

This is a lot better than nothing, but still somewhat regrettable.

 


>>
You can only bind to dependency properties on dependency objects, or CLR properties. A field on your code-behind partial class is neither of these!

Since OneWayToSource databinding does permit the source not to be a dependency property, I tried the following as a “what the heck”:

 

     ItemsSource="{Binding Path=_customers, Mode=OneWayToSource}"

 

but it doesn’t seem to populate the list.

 

 

>> 2. Use an ObjectDataProvider. You can find an example of this in a recent article I published on codeproject

I’ll take a look at that!

Coordinator
Nov 21, 2008 at 2:17 AM
You can use x:Name attribute instead on Name property with the column and then use it in the code behind.
Nov 21, 2008 at 7:49 AM
Hi,

Thanks VamseeP, good point. You can use x:Name, however some controls, but not all, also have a Name property which maps to the same thing.

Yes, OneWayToSource an be used to bind a CLR property to a dependency property, however this will not work for two reasons:

1. OneWayToSource, where your CLR property is the source means that changes are mapped from your dependency property to your CLR property, not the other way around.

2. With your binding above, you speify a path, so that the Binding knows which property to use to obtain the data, however think for a minute about where the Binding obtains the object that this is a property of? Your bindings typically bind to a Path on your current DataContext. For example in a form you might make your Window DataContext an instance of a Person object, then bind TextBoxes to the Age and Name properties of this object. Your current DataContext does not default to an instance of your code-behidn class, it defaults to nothing!

If you really want to bind to the customers object you must do two things:

1. In your code behind do the following:

this.DataContext=this;

This ensures that the context for bindings is the Window class itself.

2. Make _customers a dependency property.

Personally, I would not bother ;-)

Colin E.



Nov 21, 2008 at 5:25 PM
Thanks, VamseeP, that works great!  Can you explain to me why that property requires the prefix for the XAML namespace, whereas on most other elements it does not?
Nov 21, 2008 at 5:37 PM
>> OneWayToSource, where your CLR property is the source means that changes are mapped from your dependency property to your CLR property, not the other way around.

Hey, I knew that!  8-)

>> If you really want to bind to the customers object you must do two things: ... Personally, I would not bother ;-)

Me neither. I'm perfectly fine with setting the ItemsSource in my C# code, since that's where I populate the source list anyway; and being able to refer to the DataGridComboBoxColumn by name (thanks to the "x:" prefix) solves the remaining problem with that.

I appreciate your help!





Coordinator
Nov 21, 2008 at 5:57 PM
Most of the other items are derived from FrameworkElement class which has a Name property in it where as DataGridColumn is directly derived from DependencyObject. Hence name property doesnt work with it. But x:Name attribute works for most of the items because it is a XAML thing.
May 12, 2010 at 8:16 PM

Can you give an example of how to use x:Name programatically instead of the column index in:

DataGridComboBoxColumn dgCbCol = (DataGridComboBoxColumn)_ordersDataGrid.Columns[2];

dgCbCol.ItemsSource = _customers;

Jun 10, 2014 at 5:49 AM
Edited Jun 10, 2014 at 5:51 AM
Hi,

Please send me the XAML and C# source code. I am trying to attach datatable to datagrid combobox column and bind object to datagrid.