navigation
 Thursday, July 10, 2008

I was recently working on a WPF form that allowed users to edit data stored in an XML file.  In the process, I learned a lot about simplifying my databinding code.  As a WPF newbie myself, I found the use of datacontexts on parent elements just pretty cool.  You can bind whole blocks of elements to the same source, and they are all updated together with almost no code-behind whatsoever.

For example, consider the following block of xml to be loaded into a WPF form

<files>
  <localfiles type="pictures" description="local picture files">
    <file name="picture1.jpg" folder="pictures/samplepictures" title="autumn leaves" size="304k" />
    <file name="picture2.jpg" folder="pictures/july2008" title="butterfly" size="139k" />
    <file name="picture3.jpg" folder="pictures/june2008" title="desert" size="269k" />
    <file name="picture4.jpg" folder="pictures/july2008" title="clouds" size="135k" />
  </localfiles>
</files>

First, I bind my textblocks to attributes of the xml elements, and wrap them in a parent element, like a stackpanel.

<StackPanel Margin="15" x:Name="spFiles">        
<TextBlock Foreground="#FF000000">Type</TextBlock> <TextBox x:Name="tbType" Width="220" Height="25" Text="{Binding Path=Attribute[type].Value}"/> <TextBlock Foreground="#FF000000">Description</TextBlock> <TextBox x:Name="tbDescription" Width="220" Height="25" Text="{Binding Path=Attribute[description].Value}"/> <TextBlock Foreground="#FF000000">Files</TextBlock>

Then I can programmatically set the datacontext of that parent element when the user opens the form. Here, "root" is a System.XML.Linq.XElement containing the root element of my xml document.

spFiles.DataContext = root.Element("localfiles");

If I want to use a selector, like a combobox, to select the file to be displayed in the form fields, I can bind the combobox to the elements of type "file" inside the datacontext.  Here's where I can also use the itemtemplate to bind the combobox items to a particular attribute of the elements themselves.  In this case, the combobox will show the names of the files.

<ComboBox x:Name="cbFiles" HorizontalAlignment="Center" Width="220" Height="25" SelectedIndex="0"
    ItemsSource="{Binding Path=Elements[file]}" IsSynchronizedWithCurrentItem="True">
    <ComboBox.ItemTemplate>
          <DataTemplate>
                <TextBlock Text="{Binding Path=Attribute[name].Value}"/>
           </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

Finally, to use the selected item of the combobox to fill the rest of the form, I wrap those controls in a stackpanel, and bind its datacontext accordingly.  Even though they are still inside the spFiles panel, they will still bind to the most immediate parent's datacontext first; in this case the spFileInfo panel.

<StackPanel x:Name="spFileInfo" DataContext="{Binding ElementName=cbFiles, Path=SelectedItem}">
    <TextBlock Foreground="#FF000000">Folder</TextBlock>
    <TextBox x:Name="tbFileFolder" Width="220" Height="25" Text="{Binding Path=Attribute[folder].Value}"/>
    <TextBlock Foreground="#FF000000">Title</TextBlock>
    <TextBox x:Name="tbTitle" Width="220" Height="25" Text="{Binding Path=Attribute[title].Value}"/>
    <TextBlock Foreground="#FF000000">Size</TextBlock>
    <TextBox x:Name="tbSize" Width="220" Height="25" Text="{Binding Path=Attribute[size].Value}"/>
</StackPanel>
</StackPanel>

Now my form will be loaded with the data, my combobox will be populated, and my folder, title, and size fields will be updated automatically when a combobox item is selected, all with basically one line of C# code!

image  image  image

Of course, since the default UpdateSourceTrigger mode of a textbox is LostFocus, any changes made will be automatically saved to the XElement root after they are entered, but I'll need to call root.Save in order to update the actual file.  I could also control the updates myself by setting the mode to Explicit in my binding XAML, and then calling UpdateSource from my code.  For more information on UpdateSourceTrigger, and on databinding in general, here's a great post on the MSDN blogs.

 |  | 
Name
E-mail
Home page

Comment (Some html is allowed: a@href@title, i, strike, u) where the @ means "attribute." For example, you can use <a href="" title=""> or <blockquote cite="Scott">.  

Enter the code shown (prevents robots):

Live Comment Preview