You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在C++/WinRT、WinUI 3中实现返回winrt::event_revoker的自定义类型事件注册器

正确实现WinRT自定义类型的INotifyPropertyChanged自动撤销器

问题根源

你之前的错误是因为winrt::event_revoker依赖公共WinRT接口的方法指针,而非implementation类的私有方法;同时构造revoker时需要传入公共接口的弱引用,而非implementation类的弱引用。

标准实现步骤

1. 调整头文件定义

在winrt::Test::implementation::MyType的头文件中,修正revoker类型声明与重载方法:

namespace winrt::Test::implementation {
struct MyType : MyTypeT<MyType>
{
    // 保留原有基础事件实现
    winrt::event_token PropertyChanged(winrt::Microsoft::UI::Xaml::Data::PropertyChangedEventHandler const& handler);
    void PropertyChanged(winrt::event_token const& token);

    // 定义基于公共接口的撤销器类型
    using PropertyChanged_revoker = winrt::event_revoker<Test::MyType>;
    // 声明带auto_revoke的重载方法
    PropertyChanged_revoker PropertyChanged(winrt::auto_revoke_t, winrt::Microsoft::UI::Xaml::Data::PropertyChangedEventHandler const& handler);

private:
    winrt::event<winrt::Microsoft::UI::Xaml::Data::PropertyChangedEventHandler> propertyChanged_;
};
}

2. 实现带自动撤销的重载方法

在cpp文件中,正确构造event_revoker:

winrt::event_token winrt::Test::implementation::MyType::PropertyChanged(winrt::Microsoft::UI::Xaml::Data::PropertyChangedEventHandler const& handler)
{
    return propertyChanged_.add(handler);
}

void winrt::Test::implementation::MyType::PropertyChanged(winrt::event_token const& token)
{
    propertyChanged_.remove(token);
}

winrt::Test::implementation::MyType::PropertyChanged_revoker 
winrt::Test::implementation::MyType::PropertyChanged(winrt::auto_revoke_t, winrt::Microsoft::UI::Xaml::Data::PropertyChangedEventHandler const& handler)
{
    // 获取公共接口的弱引用(而非implementation类的弱引用)
    auto weak_public_this = winrt::make_weak<Test::MyType>(*this);
    // 直接使用公共接口的PropertyChanged(event_token)方法作为撤销逻辑
    return PropertyChanged_revoker(weak_public_this, &Test::MyType::PropertyChanged, propertyChanged_.add(handler));
}

3. 使用撤销器并存入vector

调用方代码示例:

// 存储撤销器的容器
std::vector<winrt::Test::implementation::MyType::PropertyChanged_revoker> event_revokers;

// 创建MyType实例
auto my_type = winrt::make<winrt::Test::implementation::MyType>();

// 添加带自动撤销的事件处理器,将revoker存入vector
event_revokers.emplace_back(
    my_type.PropertyChanged(winrt::auto_revoke, [](auto&& sender, auto&& args) {
        // 处理属性变更逻辑
        winrt::hstring prop_name = args.PropertyName();
        // ...
    })
);

关键说明

  • 无需自定义unregisterPropertyChanged方法:公共接口Test::MyType已继承INotifyPropertyChanged的PropertyChanged(event_token)方法,直接复用即可。
  • 必须使用公共接口的弱引用:winrt::make_weak<Test::MyType>(*this)将implementation实例转换为公共接口的弱引用,符合event_revoker的ABI调用要求。
  • 避免修改WinRT库内部实现:你的临时方案修改了event_revoker的源码,会破坏库的兼容性与规范性,标准实现完全无需此类操作。

内容的提问来源于stack exchange,提问作者ridilculous

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 06:10:30