我完全按照在Setter.Value结构中设置事件处理程序中所述的方式来解决问题.但我想理解为什么问题的作者提供的解决方案不起作用.看起来我错过了一些概念.
Cod*_*ked 15
这似乎是生成XAML代码隐藏的一个错误.除了XAML文件的用户代码隐藏之外,还有一个"编译器"生成的版本,它定义了命名元素的InitializeComponent和类字段(即x:Name).
举个简单的例子:
<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 />
Run Code Online (Sandbox Code Playgroud)
如果你运行它,你将得到以下异常:
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:
Run Code Online (Sandbox Code Playgroud)
生成的代码隐藏文件可以在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;
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是生成的代码试图将其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 />
Run Code Online (Sandbox Code Playgroud)
然后生成的代码是:
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;
}
Run Code Online (Sandbox Code Playgroud)
根据我的测试,代码生成器似乎为每个控件分配一个ID,它需要"连接"或添加处理程序/支持字段.在ContextMenu被包含在内联的情况下(即第一个示例),它的事件处理程序被分配给窗口内的根元素,并且没有获得它自己的ID.
如果我们将Button更改为包含在Grid中,则上面的异常将指示它无法将MenuItem强制转换为Grid.因为现在Grid是根元素.这表明它与Style目标的类型无关.
当ContextMenu作为单独的资源包含时,代码生成器似乎正确地为其分配了ID,因此可以正确附加处理程序.
最终,这是XAML代码生成器中的一个错误.
| 归档时间: |
|
| 查看次数: |
3230 次 |
| 最近记录: |