我完全按照Setting event handlers inside a Setter.Value structure中所述的方式面對問題。但我想明白爲什麼問題作者提供的解決方案不起作用。看起來我錯過了一些概念。爲什麼「在Setter.Value結構中設置事件處理程序」會產生編譯錯誤?
7
A
回答
13
這似乎是XAML代碼隱藏代中的一個錯誤。除了用於XAML文件的用戶代碼隱藏之外,還有一個「編譯器」生成的版本,該版本爲命名元素(即x:Name)定義InitializeComponent和類字段。
給出一個簡單的例子:
<Window.Resources>
<Style TargetType="Button">
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu>
<MenuItem Header="Header" Click="MenuItem_Click"/>
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Button />
如果你運行它,你會得到以下異常:
System.Windows.Markup.XamlParseException occurred
Message='Set connectionId threw an exception.' Line number '13' and line position '8'.
Source=PresentationFramework
LineNumber=13
LinePosition=8
StackTrace:
at System.Windows.Markup.XamlReader.RewrapException(Exception e, IXamlLineInfo lineInfo, Uri baseUri)
InnerException: System.InvalidCastException
Message=Unable to cast object of type 'System.Windows.Controls.MenuItem' to type 'System.Windows.Controls.Button'.
Source=Windows7Theme
StackTrace:
at Windows7Theme.MainWindow.System.Windows.Markup.IComponentConnector.Connect(Int32 connectionId, Object target) in c:\Users\TJoe\Documents\Visual Studio 10\Projects\Windows7Theme\Windows7Theme\MainWindow.xaml:line 13
at MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetConnectionId(Object root, Int32 connectionId, Object instance)
InnerException:
生成的代碼隱藏文件可以在obj
文件夾中找到,所以如果我們檢查,我們可以看到下面的代碼:
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) {
switch (connectionId)
{
case 1:
#line 13 "..\..\..\MainWindow.xaml"
((System.Windows.Controls.Button)(target)).AddHandler(System.Windows.Controls.MenuItem.ClickEvent, new System.Windows.RoutedEventHandler(this.MenuItem_Click));
#line default
#line hidden
return;
}
this._contentLoaded = true;
}
的發行H ere是生成的代碼試圖將MenuItem
轉換爲Button
。如果我們改變我們的樣本,像這樣:
<Window.Resources>
<ContextMenu x:Key="ContextMenuKey">
<MenuItem Header="Header" Click="MenuItem_Click"/>
</ContextMenu>
<Style TargetType="Button">
<Setter Property="ContextMenu"
Value="{StaticResource ContextMenuKey}" />
</Style>
</Window.Resources>
<Button />
然後生成的代碼是:
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) {
switch (connectionId)
{
case 1:
#line 10 "..\..\..\MainWindow.xaml"
((System.Windows.Controls.MenuItem)(target)).Click += new System.Windows.RoutedEventHandler(this.MenuItem_Click);
#line default
#line hidden
return;
}
this._contentLoaded = true;
}
根據我的測試中,它出現在代碼生成的ID分配給每個控件,它需要「連接「或爲其添加處理程序/後臺字段。在ContextMenu被內聯包含的情況下(即第一個例子),它的事件處理程序正被分配給窗口內的根元素並且沒有得到它自己的ID。
如果我們將Button更改爲包含在網格中,那麼上面的異常將表示它無法將MenuItem投射到網格。因爲現在網格是根元素。這表明它與Style對象的類型無關。
當ContextMenu作爲單獨的資源包含在內時,代碼生成器似乎正確地爲其分配了一個ID,因此可以正確連接處理程序。
最終,這是XAML代碼生成器中的一個錯誤。
+2
感謝您的精彩解釋。我認爲你可以將這個bug提交給wpf開發者。 – alehro 2011-04-13 10:29:12
相關問題
- 1. 在Setter.Value結構中設置事件處理程序
- 2. 事件處理程序子例程中的編譯錯誤
- 3. 爲什麼編譯此代碼會產生錯誤?
- 4. 爲什麼編譯器會產生錯誤?
- 5. 爲什麼Eclipse jar文件在應用程序沒有錯誤時會產生編譯錯誤?
- 6. 爲什麼我不能設置批量事件處理程序?
- 7. 爲什麼用-fllvm編譯這個Haskell程序會產生不同的結果?
- 8. C#CS0079事件處理編譯錯誤
- 9. 爲什麼設置readPreference最接近不會產生主錯誤?
- 10. 爲什麼會產生以下錯誤?
- 11. 爲什麼SQLite3不會產生錯誤
- 12. 爲什麼程序調用strncat()會產生分段錯誤?
- 13. 爲什麼小數在零除後會產生編譯時錯誤?
- 14. 爲什麼存在layout和normal-mdpi不會產生編譯時錯誤?
- 15. 編譯GLM會產生大量錯誤
- 16. 代碼會產生編譯錯誤
- 17. 爲什麼Java常量除以零產生編譯時錯誤?
- 18. 編譯器如何生成事件處理程序代碼?
- 19. .net Listbox不會用JavaScript事件處理程序進行編譯?
- 20. 爲什麼這個覆蓋方法聲明會產生編譯錯誤?
- 21. 爲什麼將char *傳遞給字符串參數會產生編譯錯誤?
- 22. 在VS/C#編譯事件中處理錯誤
- 23. 設置事件處理程序?
- 24. 程序不編譯。什麼是錯誤
- 25. 在xcode中編譯Titanium(Appcelerator)應用程序會產生警告和錯誤
- 26. 爲什麼不編譯編譯錯誤?
- 27. 爲什麼返回在onclick事件處理程序中使用?
- 28. 爲什麼在事件處理程序中使用'return'?
- 29. 爲什麼GWT編譯錯誤不會破壞Maven構建?
- 30. 事件處理,數據結構與程序設計,JAVA
通過*「由問題作者提供的解決方案」*您的意思只是它不起作用附加像這樣的處理程序,對不對? (只是爲了避免混淆,因爲我確實提供了一個「解決方案」,涉及使用'EventSetters',它可以工作) – 2011-04-12 12:04:31
是的,你是對的。 – alehro 2011-04-12 12:19:58