R – WPF: Problem with ItemsControl datatemplate as a user control

data-bindingitemscontroluser-controlswpf

This works fine:

 <ItemsControl ItemsSource="{Binding Persons}">
   <ItemsControl.ItemsPanel>
     <ItemsPanelTemplate>
       <StackPanel Orientation="Vertical" />
     </ItemsPanelTemplate>
   </ItemsControl.ItemsPanel>
   <ItemsControl.ItemTemplate>
     <DataTemplate>
       <StackPanel Orientation="Horizontal">
         <TextBlock Text="{Binding Path=FirstName}"/>
         <TextBlock Text="{Binding Path=LastName}"/>
       </StackPanel>
     </DataTemplate>
   </ItemsControl.ItemTemplate>
 </ItemsControl>

But, I want to make use of a User Control in place of the stack panel with two TextBlocks using something like:

  <DataTemplate>
    <jasControls:NameView/>
  </DataTemplate>

But, with this and a million other syntaxes, the NameView shows nothing, yet it works fine in a separate test, outside the ItemsControl, with explicitly set (dependency) property – e.g.

  <jasControls:NameView FName="{Binding Path=Person.FirstName}"  />

I can find hardly any examples of this anywhere, and need to know how to specify the properties of the user control – or how can the user control 'receive' the individual item type (a Person)? What syntax to use? Do I need to specify the datatype? Is ItemsControl causing a problem or should any similar control do e.g. ListBox? Can I design it so that the user control gets an entire Person object? What dependency properties do I need in the user control? In short, how to get data into the user control?! The actual business types involved will be a bit more complicated involving some logic in the user control, hence my desire to use a user control.

ANY direction on this will be very gratefully received – TIA

Best Answer

Assuming your Persons collection has many Person objects in it, the DataContext property of your NameView control will automatically be set to the Person object.

You wouldn't need any dependency properties to achieve this feat. Your NameView usercontrol would simply be:

<UserControl ...>
   <StackPanel Orientation="Horizontal">
      <TextBlock Text="{Binding FirstName}"/>
      <TextBlock Text="{Binding LastName}"/>
   </StackPanel>
</UserControl>

You should have no codebehind to get this information to display.

From there, you should be able to access the Person object from the DataContext property:

Person person = this.DataContext as Person;