Where does a Binding find its data?


If you’ve look at much WPF Xaml you’ve probably seen bindings like this:


 


<TextBlock Text={Binding Name />


 


… which binds the Text property of the TextBlock to the Name property of some data object.


 


The question that begets is:  where does the data come from?  The rest of this post looks at the answer.


 


 


Properties on Binding


 


The Binding class has a few properties that provide ways to let you set the source of the data onto the Binding, depending on what works best for your situation.   Binding looks like this:


 


public class Binding : BindingBase


{


   


    public object Source { get; set; }


    public string ElementName { get; set; }


    public RelativeSource RelativeSource { get; set; }


   


}


 


 


The Source Property


 


The most straightforward way to set the source of the Binding is to use the Source property.  One of the more common ways to do that is to reference the data out of a resource dictionary:


 


<Grid>


  <Grid.Resources>


    <Int32Collection x:Key=DataSource1>1,2,3</Int32Collection>


  </Grid.Resources>


 


  <ListBox ItemsSource={Binding Source={StaticResource DataSource1}} />


</Grid>


 


(This example creates a ListBox with 3 entries in it, labeled “1”, “2”, and “3”.)


 


You can be even more explicit by setting the Source directly, specifying the Binding in full Xml syntax (rather than the above markup extension syntax):


 


<Grid>


  <ListBox>


    <ListBox.ItemsSource>


      <Binding>


        <Binding.Source>


          <Int32Collection>1,2,3</Int32Collection>


        </Binding.Source>


      </Binding>


    </ListBox.ItemsSource>


  </ListBox>


</Grid>


 


You can also set the Binding.Source by referencing a static member:


 


namespace MyNamespace


{


    class MyClass


    {


        public static List<int> MyData;


        static MyClass()


        {


            MyData = new List<int>();


            MyData.Add(1);


            MyData.Add(2);


            MyData.Add(3);


        }


 


    }


}


 



 


<Page


    xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation


    xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml


    xmlns:my=”clr-namespace:MyNamespace” >


 


  <ListBox ItemsSource={Binding Source={x:Static my:MyClass.MyData}} />


 


</Page>


 


 


The ElementName Property


 


Aside from the Binding.Source property, you can also reference your data by name, using Binding.ElementName, such as:


 


<StackPanel>


  <TextBox Name=TextBox1 />


  <Button Content={Binding Text, ElementName=TextBox1} />


</StackPanel>


 


(This example causes the button label to be whatever you type into the text box.)


 


 


The RelativeSource Property


 


The RelativeSource property provides a way to tell the Binding to look around where it’s used to find its source.  For example, the ‘Self’ RelativeSource binds to the object on which the Binding is placed, such as in the following (which creates a TextBlock that says “Hi”):


 


<TextBlock Tag=Hi Text={Binding Tag, RelativeSource={RelativeSource Self}} />


 


As another example, the following binds the TextBlock.Text property to the Grid in its ancestry (again displaying “Hi” in this case):


 


<Grid Tag=Hi>


 


  <Border Background=LightGray>


    <TextBlock


         Text={Binding Tag, RelativeSource={RelativeSource FindAncestor, AncestorType=Grid}} />


  </Border>


 


</Grid>


 


The other two modes of a RelativeSource are TemplatedParent and PreviousData.


 


Explicit DataContext Property


 


A common way the Binding can get its source is via a DataContext property set on an element (on the element itself, not on the Binding).  For (a rather boring) example, this creates a Button that says “Click”:


 


<Button Content={Binding}>


  <Button.DataContext>


    <sys:String>Click</sys:String>


  </Button.DataContext>


</Button>


 


This gets more interesting and typical if you set the DataContext somewhere else, usually on the root of the page/window.  That works because the DataContext property inherits.  The following example shows that by setting the DataContext onto the root.  In this case, it is set to be an XmlDataProvider which is querying a Yahoo web service for the weather in Barrow, Alaska.  Since the DataContext inherits, Bindings throughout the page have access to it automatically.  Note also in this case that since we’re binding to XML, the Bindings are using XPath syntax.


 


<Page   


    xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation 


    xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml 


    >


 


  <Page.DataContext>


    <XmlDataProvider


            Source=http://xml.weather.yahoo.com/forecastrss?p=99723 


            XPath=/rss/channel/>


  </Page.DataContext>


 


  <Border BorderBrush=Black


          BorderThickness=1 Width=370 Height=170 CornerRadius=6>


    <StackPanel>


 


      <!– Image for “Yahoo! News” –>


      <Image Margin=15,15,0,0


                   Stretch=None 


                   HorizontalAlignment=Left


                   Source={Binding XPath=image/url} />


 


      <!– Text to say e.g. “Yahoo! Weather – Bellevue, WA”, with a hyperlink to a


           detailed weather page –>


      <TextBlock Margin=15,15,0,0>


        <Hyperlink NavigateUri={Binding XPath=item[1]/link}>


          <TextBlock Text={Binding XPath=title}/>


        </Hyperlink>


      </TextBlock>


 


      <!– Text to say e.g. “Conditions for Belleveue, WA at 9:53am …” –>


      <TextBlock FontWeight=Bold    Margin=15,15,0,0


                 Text={Binding XPath=item[1]/title}/>


 


      <!– Weather details  –>


      <TextBlock Margin=15,0,0,0>


 


        <!– Text to say current condition and temp –>


        <TextBlock>


          <TextBlock.Text>


            <Binding >


              <Binding.XPath>


                item[1]/*[local-name()=”condition” and


                namespace-uri()=”http://xml.weather.yahoo.com/ns/rss/1.0“]/@text


              </Binding.XPath>


            </Binding>


          </TextBlock.Text>


        </TextBlock>,


        <TextBlock>


          <TextBlock.Text>


            <Binding >


              <Binding.XPath>


                item[1]/*[local-name()=”condition” and


                namespace-uri()=”http://xml.weather.yahoo.com/ns/rss/1.0“]/@temp


              </Binding.XPath>


            </Binding>


          </TextBlock.Text>


        </TextBlock>°


        <TextBlock>


          <TextBlock.Text>


            <Binding >


              <Binding.XPath>


                *[local-name()=”units” and


                namespace-uri()=”http://xml.weather.yahoo.com/ns/rss/1.0“]/@temperature


              </Binding.XPath>


            </Binding>


          </TextBlock.Text>


        </TextBlock>


        <LineBreak/>


 


        <!– Text to say sunrise/sunset times –>


        Sunrise:


        <TextBlock>


          <TextBlock.Text>


            <Binding >


              <Binding.XPath>


                *[local-name()=”astronomy” and


                namespace-uri()=”http://xml.weather.yahoo.com/ns/rss/1.0“]/@sunrise


              </Binding.XPath>


            </Binding>


          </TextBlock.Text>


        </TextBlock>, sunset:


 


        <TextBlock>


          <TextBlock.Text>


            <Binding >


              <Binding.XPath>


                *[local-name()=”astronomy” and


                namespace-uri()=”http://xml.weather.yahoo.com/ns/rss/1.0“]/@sunset


              </Binding.XPath>


            </Binding>


          </TextBlock.Text>


        </TextBlock>


      </TextBlock>


    </StackPanel>


 


  </Border>


</Page>


 


… Sunrise at midnight, sunset at noon:


 


[ImageAttachment]


 


 


Implicit DataContext


 


Finally, there are a couple of places where the DataContext gets set automatically for you.  That usually happens with ContentControl (e.g. Button) and ItemsControl (e.g. ListBox). 


 


Here’s a ContentControl example.  In this markup we have a DataTemplate set up in a ResourceDictionary so that it will be used for any ContentControl that has a String as its content.  So it’s automatically picked up in the subsequent Button.  In that DataTemplate, we have a binding to the data item, which in this case is the ContentControl.Content.  Therefore what we get here is a Button that says “Click” in bold italic.


 


<Page   


    xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation 


    xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml 


    xmlns:sys=clr-namespace:System;assembly=mscorlib>


 


  <Page.Resources>


    <DataTemplate DataType={x:Type sys:String}>


      <!– The Text property is bound to the Content property of


           whatever ContentControl with which this DataTemplate is used –>


      <TextBlock Text={Binding} FontStyle=Italic FontWeight=Bold />


    </DataTemplate>


  </Page.Resources>


 


  <Button>Click</Button>


 


</Page>


 


 


And here’s an ItemsControl example.  In this markup, we have a ListBox bound to an integer collection again (using the inherited DataContext as the source), but this time we have an item template, which is a  template to use when displaying the items in the ListBox.  And within that item template, the DataContext is again automatically set to be the item


 


<Page   


    xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation 


    xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml >


 


  <Page.DataContext>


    <Int32Collection>1,2,3</Int32Collection>


  </Page.DataContext>


 


  <!– ItemsSource is bound to the DataContext (Int32Collection) –>


  <ListBox ItemsSource={Binding} >


    <ListBox.ItemTemplate>


      <DataTemplate>


 


        <DataTemplate.Triggers>


          <!– Within the DataTemplate, the DataContext is set to be the data item.


               So this DataTrigger.Binding property’s DataContext is going to be


               the item (1, 2, or 3) –>


          <DataTrigger Binding={Binding} Value=2>


            <Setter Property=TextBlock.FontStyle Value=Italic />


            <Setter Property=TextBlock.FontWeight Value=Bold />


          </DataTrigger>


        </DataTemplate.Triggers>


 


        <Border Padding=10>


          <!– Similarly this Text property is bound to the item (1, 2, or 3) –>


          <TextBlock Text={Binding} />


        </Border>


      </DataTemplate>


    </ListBox.ItemTemplate>


  </ListBox>


</Page>


 


 


 

barrow.jpg

Comments (5)

  1. Microsoft Surface: What WPF Can Do For You [Via: Ashish Shetty ] Where does a Binding find its data?…

  2. SaiedMic says:

    Hey Mike, this is a really nice writeup on XAML binding… maybe one of the better ones out there… thanks. =D

  3. joewood says:

    Great write-up.  A good resource to point ppl to.

  4. sagiy22@hotmail.com says:

    Thank you very much for this helpful and informative article!

    There’s more information on this PDF…

    http://docs.google.com/viewer?url=http://www.nbdtech.com/Free/WpfBinding.pdf&pli=1