<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      《深入淺出WPF》:8.3.2 自定義路由事件 事件注冊類型為 EventHandler<ReportTimeEventArgs>,但.NET 事件包裝器類型為 RoutedEventHandler

      image

      事件處理器的簽名要和注冊時的簽名一致:

      image

      包裝器的參數類型為基類型,事件處理器的參數類型為子類型,根據委托協變,可以把子類型參數的委托賦值給基類型參數的委托
      image

      以下是deepseek回答:

      這是一個非常好的問題,它觸及了 WPF 路由事件中一個關于類型兼容性和歷史設計的細節。

      你的觀察是準確的:代碼中確實存在一個看似不一致的地方。我們來分析一下為什么可以這樣做,以及為什么要這樣設計。

      核心原因:類型兼容性與 .NET 事件協變/逆變

      1. 事件注冊時的類型

        public static readonly RoutedEvent ReportTimeEvent = EventManager.RegisterRoutedEvent(
            "ReportTime", RoutingStrategy.Bubble, typeof(EventHandler<ReportTimeEventArgs>), typeof(TimeButton));
        

        這里,RegisterRoutedEvent 方法的第三個參數是 handlerType,它指定了哪個委托類型可以處理這個事件。這里使用的是 EventHandler<ReportTimeEventArgs>。這意味著事件處理程序的簽名必須是 void MethodName(object sender, ReportTimeEventArgs e)。

      2. .NET 事件包裝器

        public event RoutedEventHandler ReportTime
        {
            add { AddHandler(ReportTimeEvent, value); }
            remove { RemoveHandler(ReportTimeEvent, value); }
        }
        

        這里你發現,公共事件的類型是 RoutedEventHandler。RoutedEventHandler 的簽名是 void MethodName(object sender, RoutedEventArgs e)。

        那么問題來了:RoutedEventHandler 類型的委托怎么能被添加到期望 EventHandler<ReportTimeEventArgs> 類型委托的事件中呢?

      3. 關鍵的兼容性.NET 委托的協變

        • RoutedEventHandler 的參數是 RoutedEventArgs
        • 你的自定義參數 ReportTimeEventArgs 繼承自 RoutedEventArgs。
        • 在 .NET 中,委托支持協變。這意味著一個期望接收基類參數(如 RoutedEventArgs)的委托,可以安全地引用一個接收派生類參數(如 ReportTimeEventArgs)的方法。
        • 反過來,EventHandler<ReportTimeEventArgs> 可以被視為 RoutedEventHandler 的一個“更具體”的版本。因為任何能處理 RoutedEventArgs 的方法,必然也能處理它的子類 ReportTimeEventArgs(這是“里氏替換原則”的體現)。編譯器允許這種賦值。

        因此,當你寫 local:TimeButton.ReportTime="ReportTimeHandler" 時,XAML 編譯器和運行時知道你的 ReportTimeHandler 方法符合 EventHandler<ReportTimeEventArgs> 的簽名,所以它可以安全地工作。

      為什么要包裝成 RoutedEventHandler 類型?

      既然技術上允許,那么設計上為什么選擇 RoutedEventHandler 而不是 EventHandler<ReportTimeEventArgs> 呢?這主要是出于一致性和習慣。

      1. 與 WPF 內置事件保持一致:WPF 中絕大多數路由事件(如 Button.Click、Mouse.MouseDown)都使用 RoutedEventHandler 作為其公共事件的委托類型。即使它們的事件參數是更具體的類型(如 MouseButtonEventArgs 繼承自 RoutedEventArgs),它們的公共事件也仍然定義為 RoutedEventHandler。你的自定義事件遵循了這一慣例,使得它看起來和用起來都像一個“標準”的 WPF 路由事件。

      2. 簡化 XAML 書寫:在 XAML 中,當你輸入 Button.Click= 時,智能感知和編譯器期望的是一個 RoutedEventHandler 類型的方法。如果你的自定義事件也使用 RoutedEventHandler,那么開發者在為你的 TimeButton.ReportTime 事件指定處理程序時,會有完全一致的體驗。他們不需要去記憶一個特殊的 EventHandler<ReportTimeEventArgs> 類型。

      3. 歷史原因EventHandler<T> 泛型委托是在 .NET Framework 2.0 中引入的,而 WPF 的部分設計可能更早,或者為了與早期的設計模式保持一致,選擇了使用非泛型的 RoutedEventHandler。這個習慣被保留了下來。

      總結

      • 技術上可行:因為委托協變,EventHandler<ReportTimeEventArgs>RoutedEventHandler 是兼容的。ReportTimeHandler 方法的簽名最終匹配的是事件注冊時指定的 EventHandler<ReportTimeEventArgs>。
      • 設計上合理:將公共事件包裝為 RoutedEventHandler 類型,是為了與 WPF 框架中其他所有路由事件保持一致,提供統一的編程體驗。

      所以,這并不是一個錯誤,而是一個遵循 WPF 慣例的、經過深思熟慮的設計。它保證了自定義路由事件在行為和用法上與原生事件無縫集成。

      posted @ 2025-09-27 21:10  竹樓風雨聲  閱讀(16)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 成人嫩草研究院久久久精品| 二区三区亚洲精品国产| 国产美女永久免费无遮挡| 人妻饥渴偷公乱中文字幕| 蜜臀av一区二区三区日韩| 国产一区在线播放av| 日韩乱码视频一区二区三区| 亚洲第一精品一二三区| 亚洲国产午夜福利精品| 久久这里只精品热免费99| 成人精品视频一区二区三区尤物| 奇米四色7777中文字幕| 色伦专区97中文字幕| 苍梧县| 麻豆国产97在线 | 欧美| 国产精品日日摸夜夜添夜夜添无码| 国产va在线观看免费| 国产精品久久久久影院亚瑟| 成人免费乱码大片a毛片| 中文字幕日韩精品有码视频 | 人人爽人人爽人人片a免费| 乱码精品一区二区亚洲区| 国产精品XXXX国产喷水| 精品少妇av蜜臀av| 国产精品偷乱一区二区三区| 日本一区二区三区专线| 陇南市| 亚洲欧洲一区二区综合精品| 亚洲岛国成人免费av| 国产成人精品电影在线观看| 伊人久久大香线蕉综合网| 高清无码爆乳潮喷在线观看| 日本免费一区二区三区最新vr| 自拍偷自拍亚洲精品播放 | 99精品日本二区留学生| 永寿县| 久久精品国产福利一区二区 | 成人国产一区二区三区精品| 在线中文字幕国产一区| 久久精品国产国产精品四凭| 亚洲国产一区二区精品专|