在 DataTemplate 中使用(不受支持的)事件处理程序时没有警告或错误

No warning or error when using (unsupported) event handler inside DataTemplate

场景

Silverlight 应用程序的视图中考虑以下 XAML:

<ListBox ItemsSource="{Binding Items}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}" MouseLeftButtonDown="Item_Clicked" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

未调用事件处理程序。显然,事件处理程序在 DataTemplate 中不起作用。

在编译时和运行时都没有警告或错误。此外,MSDN DataTemplate reference 未指定有关事件处理程序的任何限制。

IntelliSense 甚至 "helps" 我 <New Event Handler>Navigate to Event Handler。处理程序放在视图的代码后面。

问题

  1. 微软规定的行为吗?
  2. 这是 VS2010 中的已知错误吗?
  3. 为什么编译器不发出错误或 至少一个警告?

备注

我知道如何解决这个问题,因为这个问题在这个网站上经常被报告。我想知道为什么这会默默地失败。

"Silent error" 在编写 .NET 代码时永远不会让您走得太远,错误永远不会消失。我将描述解决此类问题的一般方法,让您自动进入 "why" 并让您有机会 google 解决方案。

您需要了解的一个重要实现细节是构建应用程序时如何处理 XAML。它由代码生成器解释,它自动生成存储在项目的 obj\Debug 目录中的 C# 代码。构建后,您会在那里找到 *.g.cs 个文件。看看它们,理解它们应该不难,从标记自动生成的代码用 #line 指令注释。

查看 Silverlight 版本,MainPage.g.cs,显示很少的代码(已编辑以适合):

   public partial class MainPage : System.Windows.Controls.UserControl {
       internal System.Windows.Controls.Grid LayoutRoot;
       private bool _contentLoaded;

       public void InitializeComponent() {
          // etc..
       }
   }

在任何地方都没有出现 MouseLeftButtonDown 事件的迹象,这当然不令人鼓舞。

使用示例 WPF 应用执行完全相同的操作。现在看看 MainWindow.g.cs(再次编辑以适应和删除无聊的部分):

   public partial class MainWindow : System.Windows.Window,
                      System.Windows.Markup.IComponentConnector, 
                      System.Windows.Markup.IStyleConnector {
       private bool _contentLoaded;

       public void InitializeComponent() {
           //...
       }

       void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) {
           //...
       }

       void System.Windows.Markup.IStyleConnector.Connect(int connectionId, object target) {
           switch (connectionId)
           {
           case 1:

           #line 9 "..\..\MainWindow.xaml"
           ((System.Windows.Controls.TextBlock)(target)).MouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(this.Item_Clicked);
           //...
           break;
           }
       }

大不同,现在您 看到 MouseLeftButtonDown 事件回来了。显然,IStyleConnector 界面有助于订阅该事件。

所以去看看那个界面的MSDN article。相当简短,这是你不应该知道的内部管道,描述是:

Provides methods used internally by the WPF XAML parser to attach events and event setters in compiled XAML.

当然,与您要完成的目标完全匹配。该文章中最重要的是版本信息部分。在 .NET Framework 中受支持,但 Silverlight 列出。

这为您提供了 "why",必要的管道在 Silverlight 中根本不可用。否则不足为奇,Silverlight 最重要的属性是它 ,允许快速下载,当用户浏览到使用的网页时不会减慢用户的速度它。它只能通过删除东西来变小。

所以,显然你应该自己提供管道。你怎么做到这一点?受启发的 google 查询是 silverlight datatemplate event. The very first hit is a winner, a question,它试图完全 您正在做的事情。如果您需要更多帮助,可以使用更多相关匹配项。