为什么这个基本绑定失败并出现异常?

时间:2014-04-16 04:03:53

标签: c# wpf xaml binding binding-expressions

任何人都可以解释为什么代码下面TagObject的绑定会抛出以下绑定异常吗?

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')

我怀疑是因为TagObject本身不是FrameworkElement的子类,因此它本身没有数据上下文,因此不知道如何解决XAML绑定。

为了测试,我将TagObject的基本类型更改为FrameworkElement,果然,绑定错误消失了,但Value仍然没有改变。我的理论是,虽然绑定现在有效,TagObject不是视觉树的一部分,因此它没有继承它的DataContext

我也尝试过提供' TextBlock a name, then specifying it as the ElementName in the binding, but that again threw a binding exception. In this case, my suspicion is that it can't find the named element because TagObject`仍然不是可视化树的一部分,即使上面有基类更改。

为了记录,我知道一个解决方案是简单地隐藏ValueConverter背后的对象创建以包装它,但我想知道是否有一个仅XAML解决方案来解决该绑定在TagObject

这是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>

这不起作用......

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

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

</TextBlock>

以下是代码:

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); }
        }
    }

}

1 个答案:

答案 0 :(得分:0)

我在VS2013解决方案中重新创建了示例代码,并复制了您所看到的内容。绑定似乎发生得很好,但是 - 它正在吐出那些恼人的错误消息。经过一些研究,似乎这是一个已知的错误 - 我看到其他人也抱怨它。绑定工作正常。据我所知,问题在于,对于ItemsSources,WPF在组成可视化树时尝试优化样式和数据模板的评估,有时在实际可用的绑定之前执行此操作。元素。在您的情况下,TextBlock已经可用,并且它具有绑定值,但其中的Tag属性在此之前组成,因此会抱怨缺少FrameworkElement(稍后,不再缺少)。

我认为这不是WPF团队的一个令人鼓舞的迹象,因为这似乎是一个非常简单的场景。正确的代码永远不应该发出警告或错误。