Bind to methods with ObjectDataProvider
Two classes inherit from DataSourceProvider. XmlDataProvider and ObjectDataProvider. ObjectDataProvider wraps an object and allows you to bind to the wrapped object in XAML. The ObjectDataProvider has a ConstructorParameters-Property for creating an object by using a constructor with parameters.
The cool thing is that a Data Binding to the wrapped object of the ObjectDataProvider is not all. With ObjectDataProvider you can even bind to a static method or to an instance method of the wrapped object. I’ll show you an example.
Just think about a really simple ComboBox that allows the user to chose some colors. Between the name of the color a rectangle filled with the color should be displayed (In WPF this is quite easy. You haven’t to create eventhandlers like you would do in Windows Forms. There you consumed the DrawItem-event of the ComboBox and used the Graphics-object to do a little bit of GDI+. In WPF GDI+ is gone). WPF’s Color class doesn’t have a name property. So just create a static class ColorHelper with one static method GetColorNames that returns an IEnumerable<string> and uses reflection to iterate over all public static properties of the Colors class that all contain Color-objects.
public static class ColorHelper
{
public static IEnumerable GetColorNames()
{
foreach (PropertyInfo p
in typeof(Colors).GetProperties(
BindingFlags.Public | BindingFlags.Static))
{
yield return p.Name;
}
}
}
The Window in the following XAML contains an ObjectDataProvider that uses the Static GetColorNames-Method of the ColorHelper class. The ItemsSource-Property (Typ: IEnumerable) of the ComboBox is bound to the ObjectDataProvider. The ItemTemplate-Property contains a DataTemplate that specifies the Visual Tree (the "look") of an item. Thanks to TypeConverters, a SolidColorBrush-Object is created for the Fill-Property of each Rectangle specified in the DataTemplate.
<Window ...
xmlns:local="clr-namespace:SimpleObjectDataProvider">
<Window.Resources>
<ObjectDataProvider x:Key="colors"
ObjectType="{x:Type local:ColorHelper}"
MethodName="GetColorNames"/>
</Window.Resources>
<StackPanel>
<ComboBox
ItemsSource="{Binding Source={StaticResource colors}}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="1" Orientation="Horizontal">
<Rectangle Fill="{Binding}" Height="10" Width="10"
Margin="2"/>
<TextBlock Text="{Binding}" Margin="2 0 0 0"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
</Window>
The displayed, open ComboBox looks like this:
Comments (7)
Great article Thomas. One small thing: it may not work ‘as is’ because the following line:
…xmlns:local=”clr-namespace:SimpleObjectDataProvider”>
refers to the namespace ‘SimpleObjectDataProvider’ in your project. It needs to be changed to the namespace used in the readers’ own projects.
Hi Ravendarque.
Thanks for the hint. Yes, of course, the namespace in the XAML-File must be changed to the one used in your project.
Thomas
You rock man :)
tnx for great code
wow, thanks for this code,
have u any idea how can i set the parameter directly in the binding
this worky correctly ObjectDataProvider.MethodParameters
but i need example like this:
Text=”{Binding Source={StaticResource TranslateCustomer, Parameter=string1, Parameter=string2}}”
hi,
thanks for the code. helped me to know how to set the itemssource to an objectdataprovider :)
Learning WPF has been surprisingly tricky, due to the many different new “aspects” of it in comparison to ASP.NET or WinForms.
You just taught me ObjectDataSource, one down, dozens to go;
Thanks!
Great article Thomas. I actually found myself wanting to bind to methods a lot myself. In my case I ended up creating something that let me do this: {BindTo SaveObject()}. You can find it here: http://www.simplygoodcode.com/2012/08/simpler-wpf-binding.html
Thanks and happy blogging.