在参考我关于 TreeView 的问题时,建议我使用数据绑定来填充 TreView 的项目。
我在 Desktop C++ VS 2022 项目中创建了一个新的黑色应用程序、打包的 WinUI3。
这将运行并显示按钮
我更改了 MainWindow IDL:
namespace App1
{
[default_interface]
runtimeclass MainWindow : Microsoft.UI.Xaml.Window, Microsoft.UI.Xaml.Data.INotifyPropertyChanged
{
MainWindow();
String MyProperty;
}
}
我改变了.h
namespace winrt::App1::implementation
{
struct MainWindow : MainWindowT<MainWindow>
{
winrt::hstring j = L"TEXT 1";
MainWindow()
{
// Xaml objects should not call InitializeComponent during construction.
// See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent
}
winrt::hstring MyProperty();
void MyProperty(winrt::hstring);
void myButton_Click(IInspectable const& sender, Microsoft::UI::Xaml::RoutedEventArgs const& args);
winrt::event_token PropertyChanged(Microsoft::UI::Xaml::Data::PropertyChangedEventHandler const& value);
void PropertyChanged(winrt::event_token const& token);
winrt::event<Microsoft::UI::Xaml::Data::PropertyChangedEventHandler> m_propertyChanged;
};
}
namespace winrt::App1::factory_implementation
{
struct MainWindow : MainWindowT<MainWindow, implementation::MainWindow>
{
};
}
我更改.cpp:
#include "pch.h"
#include "MainWindow.xaml.h"
#if __has_include("MainWindow.g.cpp")
#include "MainWindow.g.cpp"
#endif
using namespace winrt;
using namespace Microsoft::UI::Xaml;
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
namespace winrt::App1::implementation
{
winrt::hstring MainWindow::MyProperty()
{
return j;
}
void MainWindow::MyProperty(winrt::hstring nv)
{
j = nv;
m_propertyChanged(*this, Microsoft::UI::Xaml::Data::PropertyChangedEventArgs{ L"Content" });
}
winrt::event_token MainWindow::PropertyChanged(Microsoft::UI::Xaml::Data::PropertyChangedEventHandler const& handler)
{
return m_propertyChanged.add(handler);
}
void MainWindow::PropertyChanged(winrt::event_token const& token)
{
m_propertyChanged.remove(token);
}
void MainWindow::myButton_Click(IInspectable const&, RoutedEventArgs const&)
{
MyProperty(L"YO");
}
}
最后是 XAML:
<Button x:Name="myButton" Click="myButton_Click" Content="{x:Bind MyProperty, Mode=OneWay}"></Button>
这只有效一次。它曾经调用我的属性并将“TEXT 1”设置为按钮,但是当调用时myButton_Click
调用
m_propertyChanged(*this, Microsoft::UI::Xaml::Data::PropertyChangedEventArgs{ L"Content" });
什么也没做。该按钮不会更新其内容。
我究竟做错了什么?
编辑:当我m_propertyChanged(*this, Microsoft::UI::Xaml::Data::PropertyChangedEventArgs{ L"" });
这样做时,即没有“Content”字符串,它就可以工作。
为什么?
它不能双向工作,因为您指定了
OneWay
模式(实际上我真的不知道为什么,因为它应该在没有它的情况下工作......):但你可以这样声明:
但是,当您使用 C++/WinRT 执行此操作时,您可能会收到此类错误(请注意,在 .NET 和 C# 中,它会正常工作):
这是因为
Content
is 是Object
IDL 类型(又名IInspectable
),而您的属性是String
IDL 类型(又名hstring
),并且 没有带来隐式转换C++/WinRT
,另请参阅https://github.com/microsoft/cppwinrt/issues/942因此,您可以通过创建此转换来修复它(模仿 C++/WinRT 的
base.h
to_hstring
重载),例如在 MainWindow.xaml.h 中:还要确保您的财产免受无限循环的影响:
我在这里创建了一个示例应用程序:https ://github.com/smourier/WinUI3Cpp