Friday, November 27, 2009

WPF Data Binding: Objects and XML Data

 image

ObjectDataProvider can be used to create new objects directly in xaml. However, typically objects are created in code and in such cases the binding needs to be set in code. Assuming we have these objects:

class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }

    public static Person[] Friends = new Person[] {
        new Person() { FirstName="Michael", LastName="Xu", Age=9 },
        new Person() { FirstName="Michael", LastName="Xu", Age=9 },
        new Person() { FirstName="Michael", LastName="Xu", Age=9 },
        new Person() { FirstName="Michael", LastName="Xu", Age=9 },
        new Person() { FirstName="Michael", LastName="Xu", Age=9 },
    };
}

To bind these to a ListView, create a ListView style with a data template:

<Window.Resources>

    <Style x:Key="personList" TargetType="{x:Type ListView}">
        <Setter Property="ItemTemplate">
            <Setter.Value>
                <DataTemplate>
                    <StackPanel>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding Path=FirstName}"
                                       FontWeight="Bold" />
                            <TextBlock Text="{Binding Path=LastName}"
                                       FontWeight="Bold" Margin="8,0,0,0" />
                        </StackPanel>
                        <TextBlock Text="{Binding Path=Age}" />
                    </StackPanel>
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Create a ListView control with the style:

<ListView
    Name="friendsListView"
    Style="{StaticResource personList}" />

Then create the binding in code:

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    friendsListView.ItemsSource = Person.Friends;
}

To achieve similar results with an embeded XmlDataProvider, we can directly supply data and use XPath binding (note the xmlns).

<XmlDataProvider x:Key="xmlFriends">
    <x:XData>
        <Friends xmlns="">
            <Person FirstName="Michael" LastName="Xu" Age="10" />
            <Person FirstName="Michael" LastName="Xu" Age="10" />
            <Person FirstName="Michael" LastName="Xu" Age="10" />
            <Person FirstName="Michael" LastName="Xu" Age="10" />
            <Person FirstName="Michael" LastName="Xu" Age="10" />
            <Person FirstName="Michael" LastName="Xu" Age="10" />
            <Person FirstName="Michael" LastName="Xu" Age="10" />
            <Person FirstName="Michael" LastName="Xu" Age="10" />
        </Friends>
    </x:XData>
</XmlDataProvider>

<Style x:Key="xmlPersonList" TargetType="{x:Type ListView}">
    <Setter Property="ItemTemplate">
        <Setter.Value>
            <DataTemplate>
                <StackPanel>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding XPath=@FirstName}"
                                   FontWeight="Bold" />
                        <TextBlock Text="{Binding XPath=@LastName}"
                                   FontWeight="Bold" Margin="8,0,0,0" />
                    </StackPanel>
                    <TextBlock Text="{Binding XPath=@Age}" />
                </StackPanel>
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

Bind to a ListView:

<ListView 
    Style="{StaticResource xmlPersonList}"
    ItemsSource="{Binding Source={StaticResource xmlFriends}, XPath=/Friends/Person}" />

No comments: