为什么此基本绑定失败并出现异常

本文关键字:异常 失败 绑定 为什么 | 更新日期: 2023-09-27 17:58:27

有人能解释为什么下面代码中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不是Visual Tree的一部分,因此它没有继承其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); }
        }
    }
}

为什么此基本绑定失败并出现异常

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

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