1

Can anyone explain why the binding on TagObject below code throws the following binding exception?

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Value; DataItem=null; target element is 'TagObject' (HashCode=37895910); target property is 'Value' (type 'String')

My suspicion is its because TagObject itself isn't a subclass of FrameworkElement so it doesn't have a data context itself and thus doesn't know how to resolve the XAML binding.

To test, I changed the base type of TagObject to FrameworkElement and sure enough, the binding error went away, but Value still didn't change. My theory there is although the binding was now valid, TagObject wasn't part of the Visual Tree, therefore it didn't inherit its DataContext.

I also tried giving 'TextBlocka name, then specifying it as theElementNamein the binding, but that again threw a binding exception. In this case, my suspicion is that it can't find the named element becauseTagObject` still is not part of the visual tree, even with the base-class change above.

For the record, I do know a solution would be to simply hide that object creation behind a ValueConverter to wrap it for me, but I'm wondering if there's a XAML-only solution to address that binding on TagObject.

Here's the XAML:

<Window x:Class="Test.TestWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:test="clr-namespace:Test">

    <Window.Resources>

        <DataTemplate DataType="{x:Type test:DataObject}">

            <TextBlock Text="{Binding Value}">

                <TextBlock.Tag>
                    <test:TagObject Value="{Binding Value}" />
                </TextBlock.Tag>

            </TextBlock>

        </DataTemplate>

    </Window.Resources>

    <ListBox x:Name="MainListBox" BorderThickness="0" />

</Window>

This doesn't work either...

<TextBlock x:Name="MyTextBlock" Text="Test">

    <TextBlock.Tag>
        <test:TargetObject Value="{Binding DataContext.Value, ElementName=MyTextBlock}" />
    </TextBlock.Tag>

</TextBlock>

Here's the code:

using System.Windows;
using System.Collections.ObjectModel;

namespace Test
{
    public partial class TestWindow : Window
    {
        public TestWindow()
        {
            InitializeComponent();

            var sourceItems = new ObservableCollection<DataObject>();
            for(int i = 1; i <= 10; i++)
                sourceItems.Add(new DataObject() { Value = "Item " + i});

            MainListBox.ItemsSource = sourceItems;
        }
    }

    public class DataObject : DependencyObject
    {
        public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
            "Value",
            typeof(string),
            typeof(DataObject),
            new UIPropertyMetadata(null));

        public string Value
        {
            get { return (string)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }
    }

    public class TagObject : DependencyObject
    {
        public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
            "Value",
            typeof(string),
            typeof(TagObject),
            new UIPropertyMetadata(null));

        public string Value
        {
            get { return (string)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }
    }

}
Mark A. Donohoe
  • 28,442
  • 25
  • 137
  • 286

1 Answers1

0

I recreated your sample-code in a VS2013 solution and replicated what you're seeing. The binding seems to be happening just fine, but yes - it is spitting out those annoying error messages. After some research, it appears that this is a known bug -- I see others complaining of it as well. The binding is working fine. The problem, as far as I can tell from others, is that, for ItemsSources, WPF is trying to optimize the evaluation of the styles and data-templates as it composes the visual tree, sometimes doing this before the binding is available on the actual elements. In your case, the TextBlock is already available, and it has a binding value, but the Tag property within it is composed before that and thus complains of a missing FrameworkElement (which, an instant later, is no longer missing).

I do not find this to be an encouraging sign from the WPF team, as this seems like a very simple scenario. Correct code should never be emitting warnings or errors.

JamesWHurst
  • 493
  • 8
  • 14
  • Actually, by 'XAML only' I was referring to that single binding on TargetObject, not on how to set up the ListBox. Updating my question to be more clear. And you should be able to use an ElementName in a DataTemplate provided that name is defined within that template. That works fine. I'm pretty sure the issue is that it's not a FrameworkElement and even if it was, it's not part of the visual tree, so there may not be a solution. Thanks though. – Mark A. Donohoe Apr 16 '14 at 16:45