DataTemplates And DataProviders in WPF
DataTemplate:
A data template is a piece of user interface that you’d like to apply to an arbitrary .NET object when it is rendered.
Many WPF controls have properties (of type DataTemplate) for attaching a data template appropriately.
For example, ContentControl has a ContentTemplate property for controlling the rendering of its Content object, and ItemsControl has an ItemTemplate that applies to each of its items.
Properties of Data Templates:
<ListBox x:Name=”pictureBox”
ItemsSource=”{Binding Source={StaticResource photos}}” …>
<ListBox.ItemTemplate>
<DataTemplate>
<Image Source=”{Binding Path=FullPath}” Height=”35”/>
</DataTemplate>
</ListBox.ItemTemplate>
…
</ListBox>
Value converters:
Value converters can morph a source value into a completely different target value.
They enable you to plug in custom logic without giving up the benefits of data binding.
Value converters are often used to reconcile a source and target that are different data types.
For example, you could change the background or foreground color of an element based on the value of some non-Brush data source, much like conditional formatting in Microsoft Excel.
DataProvider in WPF:
1.XmlDataProvider
2.ObjectDataProvider
XmlDataProvider:
Sample: Binding to XML file
Lets create an XML file called Books.xml
<?xml version="1.0" encoding="utf-8" ?>
<BookList>
<Book>
<Title>Grapes of Wrath</Title>
<Author>Steinbeck
</Book>
<Book>
<Title>Huckleberry Finn</Title>
<Author>Twain
</Book>
</BookList>
We can then bind this to a listbox using an XmlDataProvider
<Window x:Class="WindowsApplication14.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WindowsApplication14"
xmlns:sys="clr-namespace:System;assembly=System"
>
<Window.Resources>
<XmlDataProvider x:Key="booksResource"
XPath="BookList"
Source="Books.xml">
</XmlDataProvider>
</Window.Resources>
<Grid DataContext="{StaticResource booksResource}">
<ListBox ItemsSource="{Binding XPath=Book/Author}"></ListBox>
</Grid>
</Window>
Breaking this apart a little:
<XmlDataProvider
x:Key="booksResource" ß The name of the resource
XPath="BookList" ß Where to look in the XML tree for data
Source="Books.xml" ß The URL of the XML file to load
/>
The XmlDataProvider is keyed off the name “booksResource” and using the XPath syntax (this is an XML standard), the XmlDataProvider represents all the child elements underneath the “
” xml node in the file books.xml.
We can now reference the XmlDataProvider using the StaticResource markup extension, and set our Grid’s DataContext to represent what the XmlDataProvider is returning back to us – all the child nodes under BooksList.
<Grid DataContext="{StaticResource booksResource}">
<ListBox ItemsSource="{Binding XPath=Book/Author}"></ListBox>
</Grid>
Finally the ListBox inherits the DataContext from it’s parent Grid, but tweaks the data it wants to display – it only wants to display the Authors – so using the XPath syntax (see Appendix B) it further drills into the XML hierarchy to pull out all the Authors under the book nodes.
If instead you wish to have the data directly in the file, you can embed it underneath the XmlDataProvider – there is one catch: you have to put xmlns=”” in your root tag so validation will be skipped for your data island.
<Window x:Class="WindowsApplication14.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WindowsApplication14"
>
<Window.Resources>
<XmlDataProvider
x:Key="booksResource"
XPath="Books" >
<Books xmlns="">
<Book>
<Title>Grapes of Wrath</Title>
<Author>Steinbeck</Author>
</Book>
<Book>
<Title>Huckleberry Finn</Title>
<Author>Twain</Author>
</Book>
</Books>
</XmlDataProvider>
</Window.Resources>
<Grid DataContext="{StaticResource booksResource}">
<ListBox ItemsSource="{Binding XPath=Book/Author}"></ListBox>
</Grid>
</Window>
ObjectDataProvider:
Whereas XmlDataProvider exposes XML as a data source, ObjectDataProvider exposes a .NET object as a data source.
It opens up a few additional capabilities that you don’t get by binding to the raw object. For example, it enables you to do the following:
. Declaratively instantiate the source object with a parameterized constructor
. Bind to a method on the source object
. Have more options for asynchronous data binding
<ObjectDataProvider x:Key=”dataProvider” ObjectType=”{x:Type local:Photos}” MethodName=”GetFolderName”/>
If parameters need to be passed to the method, you can use ObjectDataProvider’s MethodParameters property (which works just like its ConstructorParameters property).
To bind to this method, you simply bind to the entire
ObjectDataProvider:
<TextBlock Text=”{Binding Source={StaticResource dataProvider}}”/>
Specifying a Path in this case would apply to the instance returned by the method.