16
votes

In WPF4.0, I have a class that contains other class types as properties (combining multiple data types for display). Something like:

public partial class Owner
{
     public string OwnerName { get; set; }
     public int    OwnerId   { get; set; }
}

partial class ForDisplay
{
    public Owner OwnerData { get; set; }
    public int Credit { get; set; }
}

In my window, I have an ItemsControl with the following (clipped for clarity):

<ItemsControl ItemsSource={Binding}>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
          <local:MyDisplayControl 
                OwnerName={Binding OwnerData.OwnerName}
                Credit={Binding Credit} />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

I then get a collection of display information from the data layer, and set the DataContext of the ItemsControl to this collection. The "Credit" property gets displayed correctly, but the OwnerName property does not. Instead, I get a binding error:

Error 40: BindingExpression path error: 'OwnerName' property not found on 'object' ''ForDisplay' (HashCode=449124874)'. BindingExpression:Path=OwnerName; DataItem='ForDisplay' (HashCode=449124874); target element is 'TextBlock' (Name=txtOwnerName'); target property is 'Text' (type 'String')

I don't understand why this is attempting to look for the OwnerName property in the ForDisplay class, rather than in the Owner class from the ForDisplay OwnerData property.

Edit It appears that it has something to do with using the custom control. If I bind the same properties to a TextBlock, they work correctly.

<ItemsControl ItemsSource={Binding}>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
          <StackPanel>
              <local:MyDisplayControl 
                        OwnerName={Binding OwnerData.OwnerName}
                        Credit={Binding Credit} />
              <TextBlock Text="{Binding OwnerData.OwnerName}" />
              <TextBlock Text="{Binding Credit}" />
          </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
1
Somehow, it's trying to find the OwnerName property on ForDisplay object. Use the following link to debug : wpftutorial.net/DebugDataBinding.html. One more question, Is OwnerName property on your MyDisplayControl a dependency property?decyclone
I see nothing wrong, assuming what you clipped isn't hiding anything relevant. Have you tried clean/rebuild of the solution? I hate this suggestion as it's equivalent to telling you to "reboot", but I have a databinding situation that SHOULD work but doesn't, I find that a clean/rebuild sometimes fixes it. Not sure why.Phil Sandler
A tentative guess: change the Binding to explicitly set the Path. ie "OwnerName={Binding Path=OwnerData.OwnerName}"Andrew Shepherd
My design is in same way . but it is throwing NullReferenceException at <DataTemplate>Gokul E

1 Answers

10
votes

Are you sure the code you posted here IS the code you use in your solution? Because, this code works for me :

XAML

<ItemsControl ItemsSource="{Binding}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding OwnerData.OwnerName}"></TextBlock>
                <TextBlock Text="{Binding Credit}" />
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Window's Loaded Event

ObservableCollection<ForDisplay> items = new ObservableCollection<ForDisplay>();

for (int i = 0; i < 10; i++)
{
    items.Add(new ForDisplay() { OwnerData = new Owner() { OwnerId = i + 1, OwnerName = String.Format("Owner #{0}", i + 1) }, Credit = i + 1 });
}

DataContext = items;