2011-04-21 189 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