.net - 带有附加属性的奇怪 WPF 错误

标签 .net wpf

我看到了奇怪的行为。我有一种强烈的感觉,这是 .net 工具链中的错误。

重现步骤:

  1. 创建 WPF 应用程序。
  2. 在该解决方案中创建类库。
  3. 在类库中定义一些公共(public)类(可以为空)。
  4. 在 WPF 应用程序中定义一些具有附加属性和 Window 的类作为目标类。
  5. 将其附加到窗口并提供值

然后你得到错误:

The object 'Window' already has a child and cannot add ''. 'Window' can accept only one child.

如果您更改结构,以便在同一程序集中具有附加属性和值类的类(可以是类库或 Wpf 应用程序)它可以正常工作。

如果您将代码放在内容之后,它也能正常工作。这给出了错误:

<Window x:Class="WpfApplication9.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:my="clr-namespace:ClassLibrary1;assembly=ClassLibrary1"
        xmlns:my2="clr-namespace:ClassLibrary1"
        Title="MainWindow" Height="350" Width="525">

    <my2:Property.MyProperty>
        <my:ValueClass />
    </my2:Property.MyProperty>

    <Grid>

    </Grid>
</Window>

这不是:

<Grid>

</Grid>    

<my2:Property.MyProperty>
    <my:ValueClass />
</my2:Property.MyProperty>

有什么想法吗?

谢谢!

最佳答案

这是由 XAML 编译的自引用方式引起的。尽管您有一个包含附加属性的程序集的命名空间引用,应用程序程序集,但实际上该程序集在您需要 XAML 编译器确定元素语法引用附加属性时正在编译过程中,并且不是普通元素。

正如您所发现的,即使在信息不完整的情况下,将附加属性放在内容之后也足以让它做出正确的选择。另一方面,知道这是问题所在,您也可以简单地将附加属性放入外部程序集中,例如放入控件库中,这样也可以避免先有鸡还是先有蛋的问题。

在一个完美的世界中,C# 编译器和 XAML 编译器将相互完全集成,这个问题将会消失,但在那之前我们必须使用变通办法。

编辑:

另一个尝试解释这个,因为它有点复杂。

当您编译应用程序程序集时,它同时包含 C# 和 XAML。在上面的示例代码中,XAML 引用在同一程序集的 C# 代码中定义的附加属性。因此,XAML 编译器需要具有应用程序程序集的编译版本,才能知道 Property.MyProperty 是附加属性。但是 C# 编译器还不能编译您的应用程序程序集,因为尚未编译 XAML。这是先有鸡还是先有蛋的问题:C# 和 XAML 都相互依赖。

必须提供一些东西,XAML 编译器继续尝试使用不完整的信息编译应用程序的 XAML 文件,即使应用程序程序集尚未编译。在这样做的过程中,它可能会犯错误,比如没有检测到在同一个程序集中定义的附加属性。为什么它有时会起作用?我们可以注意到,他们已经付出了一些努力来处理一些常见的情况,因此它似乎在大多数时间都有效,但正如您所发现的那样,它并非总是有效。

最简单的解决方案是将附加属性移动到外部程序集中。控件等附加属性通常与库相关联,因此通常不会出现问题。

关于.net - 带有附加属性的奇怪 WPF 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5746177/

相关文章:

c# - Roslyn:CSharpCompilerOptions WithUsings 的效果

c# - 如何在失去焦点时关闭 WPF 弹出窗口

c# - 公开原始模型而不是单个属性时的 INotifyPropertyChanged

c# - 如何查看文件系统目录以查看文件何时添加到其中?

asp.net - 您可以在 Web 应用程序中使用 System.Runtime.Caching.MemoryCache 吗?

c# - 线程上下文和同步上下文

.net - 对 TextBlock 和 Run 元素使用相同的样式

c# - 为什么我的 c# Windows 服务在没有任何消息写入应用程序事件日志的情况下停止运行?

wpf - 将值从百分比转换为不透明度

c# - 在最终用户机器上运行支持 Kinect 的应用程序的先决条件