C++/WinRT UWP应用中OnLaunched方法内初始化控件的问题咨询
C++/WinRT UWP应用中OnLaunched方法内初始化控件的问题咨询
嘿,我来帮你拆解这个问题!你遇到的情况其实是C++/WinRT中应用类(App)和页面类(MainPage)之间的边界与访问权限问题,咱们一步步来解决你的两个疑问:
第一个问题:如何让编译器在App.cpp中识别myButton?
首先得搞清楚核心原因:myButton是MainPage类的私有成员变量(XAML编译器自动生成的,默认访问权限是private),它属于MainPage的实例,而不是全局变量或者App类的成员。哪怕你在App.cpp里包含了MainPage.g.cpp,也只能看到MainPage类的定义,没法直接访问它的私有成员。
如果一定要在OnLaunched里操作这个按钮,有两个可行的思路:
- 给MainPage添加公共接口(推荐)
这是更符合面向对象设计的做法,不要直接暴露控件,而是在MainPage里写一个公共方法来设置按钮内容:- 打开
MainPage.h,添加一个公共成员函数:void SetButtonContent(winrt::hstring const& content); - 然后在
MainPage.cpp里实现这个方法:void MainPage::SetButtonContent(winrt::hstring const& content) { myButton().Content(winrt::box_value(content)); } - 最后在App.cpp的OnLaunched方法里,获取MainPage实例并调用这个方法:
void App::OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs const& e) { auto window = Windows::UI::Xaml::Window::Current(); if (!window.Content()) { window.Content(winrt::make<MainPage>()); } // 获取MainPage实例 auto mainPage = window.Content().as<MainPage>(); if (mainPage) { mainPage.SetButtonContent(L"Clicked"); } window.Activate(); }
- 打开
- 修改myButton的访问权限(不推荐)
你可以打开MainPage.idl(C++/WinRT项目里会自动生成这个文件),找到myButton的定义,把它的访问修饰符从private改成public。这样App.cpp里拿到MainPage实例后,就可以直接调用mainPage.myButton().Content(...)。但这种做法会破坏封装性,以后维护起来很麻烦,所以非常不推荐。
第二个问题:有没有其他方式初始化控件(不直接访问myButton)?
当然有!而且这才是UWP应用更推荐的初始化方式,完全不需要从App类里操作页面控件:
- 在MainPage的构造函数里初始化
这是最简单的方式,MainPage的构造函数里可以直接访问所有内部控件,你可以在这里设置初始内容,甚至可以读取用户设置后再动态设置:MainPage::MainPage() { InitializeComponent(); // 在这里直接设置按钮初始内容 myButton().Content(winrt::box_value(L"Clicked")); } - 利用页面的Loaded事件
如果你的初始化需要依赖页面完全加载完成(比如要获取控件的实际尺寸等),可以在MainPage的构造函数里注册Loaded事件:MainPage::MainPage() { InitializeComponent(); this->Loaded([this](auto&&, auto&&) { myButton().Content(winrt::box_value(L"Clicked")); }); } - 使用数据绑定(MVVM模式,推荐)
这是UWP官方最推荐的做法,把UI和业务逻辑解耦:- 创建一个视图模型类,包含一个
ButtonContent属性; - 在MainPage.xaml里把按钮的
Content属性绑定到这个视图模型的ButtonContent; - 不管是在App的OnLaunched里还是MainPage的构造函数里,只要更新视图模型的
ButtonContent值,按钮内容就会自动更新。这种方式完全不需要直接操作控件,代码可维护性极高。
- 创建一个视图模型类,包含一个
最后补充一句:你之前尝试包含MainPage.g.cpp没用的原因是,这个文件是XAML编译器生成的MainPage实现文件,里面的myButton是MainPage的私有成员,只有MainPage的内部成员函数才能直接访问,App类的代码不在它的作用域里,所以哪怕包含了也访问不到哦。
内容来源于stack exchange




