【问题标题】:WPF databinding error in Tag property标签属性中的 WPF 数据绑定错误
【发布时间】:2015-10-01 03:15:59
【问题描述】:
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:local="clr-namespace:son"
         x:Class="son.SonWindow">
    <Grid x:Name="myGrid">
        <Grid.Tag>
            <Label Content="{Binding ActualWidth, ElementName=myGrid}" />
        </Grid.Tag>
    </Grid>
</UserControl>

就像上面的简单代码一样,但是绑定找不到元素 myGrid。在运行期间,错误显示在输出窗口中

“System.Windows.Data 错误:4:找不到绑定源 参考'ElementName = myGrid'。绑定表达式:路径=实际宽度; 数据项=空;目标元素是'标签'(名称='');目标属性是 '内容'(类型'对象')”

我正在使用带有 .Net Framework 4.5.2 的 Visual Studio 2015 社区版。有任何想法吗?提前谢谢你。

【问题讨论】:

  • 为什么要在 Tag 属性中包装标签?如果将 Label 元素移到 Tag 之外,它会起作用。
  • @benPearce ya.. 我知道只要删除标签就可以了,但我想知道为什么上面的代码会产生错误。我只是想弄清楚该错误是否与 Tag 属性的特殊内容有关。

标签: c# wpf data-binding


【解决方案1】:

元素(其属性被绑定)应该是可视化树的一部分,以便可以完成可视化树搜索。当使用ElementNameRelativeSource 绑定时,它会执行一些内部可视化树搜索。但是在您的代码中,LabelTag 与可视化树断开连接。 Label 只是内存中的一个对象,由 Tag 属性引用。

从 .NET 4.0 开始,您可以改用 {x:Reference} 标记,如下所示:

<Grid.Tag>
    <Label Content="{Binding ActualWidth, Source={x:Reference myGrid}}" />
</Grid.Tag>

编辑

如果引用名称指向包含{x:Reference} 的某个元素,则使用{x:Reference} 可能会导致循环依赖问题。在您的情况下,它是myGrid(包含{x:Reference})。所以它不能在你的情况下使用。相反,您需要使用一些代理。这种技术看起来有点hacky,但实际上它非常漂亮。它当然也适用于任何版本的 .NET(支持 WPF):

<Grid x:Name="myGrid">
    <Grid.Resources>
        <DiscreteObjectKeyFrame x:Key="proxy" Value="{Binding ElementName=myGrid}"/>
    </Grid.Resources>
    <Grid.Tag>
        <Label Content="{Binding Value.ActualWidth, Source={StaticResource proxy}}" />
    </Grid.Tag>
</Grid>

正如您所见,Binding 将其Source 设置为StaticResource 指向DiscreteObjectKeyFrame。这是一个Freezable 对象,因此无论您使用ElementName 还是RelativeSource,为Freezable 对象的任何DependencyProperty 设置的所有绑定都可以正常工作,这非常有趣。所以我们将其Value 属性绑定到Grid(名称为myGrid)。稍后我们将LabelContent属性绑定到Freezable对象,但Path设置为Value.ActualWidthValue指向Grid,所以我们需要附加ActualWidth来绑定它到Grid.ActualWidth)。

实际上你可以使用任何Freezable 对象,但为了方便我们使用DiscreteObjectKeyFrame,它的Value 接受各种object

还有另一种技术可以在这种情况下设置绑定(断开连接的上下文),但它需要您创建自定义MarkupExtension。它当然更复杂(但一旦你熟悉了 WPF,仍然足够简单)。

【讨论】:

  • 感谢您的帮助。我用你的代码替换我的代码。但是,在设计期间,我收到一个错误对象引用未设置为对象的实例。并且在运行期间,Output 窗口中会显示一个异常。
  • 异常是抛出异常:PresentationFramework.dll 中的“System.Windows.Markup.XamlParseException” 在 PresentationFramework.dll 中发生“System.Windows.Markup.XamlParseException”类型的未处理异常附加信息:不能由于循环依赖,调用 MarkupExtension.ProvideValue。 MarkupExtension 内的属性不能引用引用 MarkupExtension 结果的对象。受影响的 MarkupExtensions 是:“System.Windows.Data.Binding”行号“7”和行位置“20”。
  • @JuniverHazoic 抱歉,我没有注意到循环问题,请查看我的编辑以获取其他解决方案。
  • 绝妙的解决方案!!!非常感谢你。我想现在我对可视化树有了更好的理解,并找到了一种解决方法来处理与上述类似的场景。
  • 很棒,因为它帮助了我;在我经历了很多次迭代和大约 2 个小时试图弄清楚如何添加一个 friggin 工具提示的意义上,这一点都不美妙。这证明 xaml 是一种反模式。任何演示系统都不应该如此复杂。
【解决方案2】:

我在 WPF 中尝试了下面的代码 sn-p 并且它工作正常。

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid x:Name="myGrid">
    <Grid.Tag>
        <Label Content="{Binding ActualWidth, ElementName=myGrid}" />
    </Grid.Tag>
</Grid>

【讨论】:

  • 这段代码看起来和 OP 的完全一样,所以你应该提供一些关于你的环境的信息,比如 .NET 的版本,你是怎么知道它工作的?这可以工作的唯一原因是在最新版本的 .NET 中它可能表现不同(改进)。至少在 .NET 4.5(和更早的版本)中这是行不通的。
  • 我在 WPF 中尝试了您的代码 sn-p,但在运行时输出窗口再次给出与上述相同的错误。
  • 我在 VS2010 WPF 应用程序(.Net Framework 4.0)中对此进行了测试。当我运行我的应用程序时,我能够看到没有任何绑定错误的窗口。
【解决方案3】:

我也尝试过复制问题,但下面的代码在 VS 2010 中运行良好。

<Window x:Class="CustomEventHandlerClick.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:CustomEventHandlerClick"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Grid x:Name="myGrid">
        <Grid.Tag>
            <Label Content="{Binding ActualWidth, ElementName=myGrid}"/>
        </Grid.Tag>
    </Grid>
   </Grid>

【讨论】:

    猜你喜欢
    • 2017-01-07
    • 1970-01-01
    • 2011-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-04
    • 1970-01-01
    • 2013-06-18
    相关资源
    最近更新 更多