2011-04-21 188 views
3

我看到奇怪的行为。我有强烈的感觉,它是.net工具链中的一个错误。连接propery的奇怪的WPF错误

重现步骤:

  1. 创建WPF应用程序。
  2. 在该解决方案中创建类库。
  3. 在类库中定义一些公共类(可以为空)。
  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> 

任何想法?

谢谢!

回答

3

这是由编译XAML的自引用方式引起的。虽然您有一个包含附加属性(应用程序程序集)的程序集的名称空间引用,但实际上,在您需要XAML编译器确定元素语法引用附加属性时,该程序集正在进行编译,不是一个普通的元素。

正如您已经发现的那样,将附加属性放在内容之后足以提示即使信息不完整也能做出正确选择。另一方面,如果知道这是问题,那么也可以简单地将附加属性放入外部程序集中,例如放入控制库中,这样也可以避免鸡与鸡的问题。

在完美的世界中,C#编译器和XAML编译器将完全相互集成,并且此问题将消失,但在此之前,我们必须使用解决方法。

编辑:

另一个试图解释这一点,因为这是一个有点复杂。

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

有些东西需要付出,而XAML编译器会继续尝试使用不完整的信息编译应用程序的XAML文件,即使应用程序集合尚未编译。在这样做的过程中,可能会出现错误,如未检测到在同一个程序集中定义的附加属性。为什么它有时会工作?我们可以注意到,他们已经付出了一些努力来处理一些常见的情况,所以它似乎在大多数情况下都能正常工作,但它不会像你发现的那样一直工作。

最简单的解决方案是将附件移动到外部装配中。无论如何,控件等附属属性通常与库相关联,所以通常不会出现问题。

+0

@Rick Sladkey我没有清楚地理解第一段,你能稍微扩展一下吗?此外,附加的属性与XAML所在的组件相同。该值位于另一个属性中。 – Andrey 2011-04-21 18:21:04

+0

@安德雷:当然。我在答案中增加了一些。 – 2011-04-21 18:59:36

+0

@Rick Sladkey谢谢,非常有趣。但是按照你的解释,我不明白为什么它在两个类中都有效:一个是属性,一个是用于XAML所在的同一个程序集的值。 – Andrey 2011-04-21 19:03:15