WinUI3 C++ 数据绑定

问题描述 投票:0回答:1

参考关于 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”字符串,它就可以工作。

为什么?

c++ xaml windows-runtime winui-3 c++-winrt
1个回答
0
投票

它不能双向工作,因为您指定了

OneWay
模式:

<Button x:Name="myButton" Click="myButton_Click" Content="{x:Bind MyProperty, Mode=OneWay}"></Button>

所以只需这样声明:

<Button x:Name="myButton" Click="myButton_Click" Content="{x:Bind MyProperty, Mode=TwoWay}"></Button>

但是当您使用 C++/WinRT 执行此操作时,您可能会收到此类错误(请注意,在 .NET 和 C# 中,它会正常工作):

MainWindow.xaml.g.hpp(155,71): error C2665: 'winrt::to_hstring': no overloaded function could convert all the argument types

这是因为

Content
是 IDL 中的
Object
类型(又名
IInspectable
),而你的属性在 IDL 中是
String
类型(又名
hstring
),并且没有隐式转换,另请参阅 https:/ /github.com/microsoft/cppwinrt/issues/942

因此,您可以修复它,例如在 MainWindow.xaml.h 中创建此转换(模仿 C++/WinRT 的

base.h
to_hstring
重载):

WINRT_EXPORT namespace winrt
{
  inline hstring to_hstring(IInspectable value)
  {
    auto pv = value.try_as<IPropertyValue>();
    if (pv && pv.Type() == PropertyType::String)
      return pv.GetString();

    return L"???";
  }
}

还要确保您的财产免受无限循环的影响:

void MainWindow::MyProperty(hstring value)
{
    if (_myProperty == value)
        return;

    _myProperty = value;
    RaisePropertyChanged(L"MyProperty");
}

我在这里创建了一个示例应用程序:https://github.com/smourier/WinUI3Cpp

© www.soinside.com 2019 - 2024. All rights reserved.