C ++ WinRT UWP XAML-привязка данных SelectedItem к свойству типа String / hstring не компилируется - PullRequest
0 голосов
/ 05 февраля 2020

Я использую Visual Studio 2019 16.4.4, Microsoft. Windows .CppWinRT 2.0.200117.5, Windows 10 1809 Pro и нацелен на 10.0.17763.0.

Я пытаюсь портировать C ++ / Приложение CX для C ++ WinRT. Я использую двустороннюю привязку данных свойства SelectedItem ComboBox к свойству типа String \ hstring, но получаю ошибку компиляции (см. Ниже).

Привязка SelectedItem свойство ComboBox для свойства типа String работает в C ++ / CX и C#. Все это также может быть связано с

C ++ WinRT UWP XAML Привязка данных ItemsSource и SelectedIndex к IObservableVector не работает

Конечно, я могу использовать Object / IInspectable в качестве типа свойства (и типа элементов в источнике элементов), но для этого требуется много стандартного кода для преобразования в и из строк, поиска правильного элемента в коллекции элементов и т. Д. c. Я хотел бы избежать этого.

Есть идеи?

1>------ Build started: Project: BlankCppWinRT, Configuration: Debug Win32 ------
1>XamlTypeInfo.g.cpp
1>D:\Dev\Samples\BlankCppWinRT\Generated Files\MainPage.xaml.g.hpp(172,50): error C2664: 'auto winrt::impl::consume_BlankCppWinRT_IMainPage<winrt::BlankCppWinRT::IMainPage>::SelectedBoxItem(const winrt::param::hstring &) const': cannot convert argument 1 from 'winrt::com_ptr<To>' to 'const winrt::param::hstring &'
1>        with
1>        [
1>            To=winrt::hstring
1>        ]
1>D:\Dev\Samples\BlankCppWinRT\Generated Files\MainPage.xaml.g.hpp(157,1): message : Reason: cannot convert from 'winrt::com_ptr<To>' to 'const winrt::param::hstring'
1>        with
1>        [
1>            To=winrt::hstring
1>        ]
1>D:\Dev\Samples\BlankCppWinRT\Generated Files\MainPage.xaml.g.hpp(172,107): message : No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>D:\Dev\Samples\BlankCppWinRT\Generated Files\winrt\impl\BlankCppWinRT.0.h(55,31): message : see declaration of 'winrt::impl::consume_BlankCppWinRT_IMainPage<winrt::BlankCppWinRT::IMainPage>::SelectedBoxItem'
1>D:\Dev\Samples\BlankCppWinRT\Generated Files\MainPage.xaml.g.hpp(157): message : while compiling class template member function 'void winrt::BlankCppWinRT::implementation::MainPageT<winrt::BlankCppWinRT::implementation::MainPage>::MainPage_obj1_Bindings::Connect(int32_t,const winrt::implements<D,winrt::BlankCppWinRT::MainPage,winrt::BlankCppWinRT::IMainPageProtected,winrt::Windows::UI::Xaml::Data::INotifyPropertyChanged,winrt::composing,winrt::Windows::UI::Xaml::Controls::IPageOverrides,winrt::Windows::UI::Xaml::Controls::IControlOverrides,winrt::Windows::UI::Xaml::Controls::IControlOverrides6,winrt::Windows::UI::Xaml::IFrameworkElementOverrides,winrt::Windows::UI::Xaml::IFrameworkElementOverrides2,winrt::Windows::UI::Xaml::IUIElementOverrides,winrt::Windows::UI::Xaml::IUIElementOverrides7,winrt::Windows::UI::Xaml::IUIElementOverrides8,winrt::Windows::UI::Xaml::IUIElementOverrides9,winrt::Windows::UI::Xaml::Markup::IComponentConnector,winrt::Windows::UI::Xaml::Markup::IComponentConnector2>::IInspectable &)'
1>        with
1>        [
1>            D=winrt::BlankCppWinRT::implementation::MainPage
1>        ]
1>D:\Dev\Samples\BlankCppWinRT\Generated Files\MainPage.xaml.g.hpp(298): message : see reference to class template instantiation 'winrt::BlankCppWinRT::implementation::MainPageT<winrt::BlankCppWinRT::implementation::MainPage>::MainPage_obj1_Bindings' being compiled
1>D:\Dev\Samples\BlankCppWinRT\ObservableStringVector.h(31): message : see reference to class template instantiation 'winrt::impl::fast_iterator<winrt::Windows::Foundation::Collections::IObservableVector<winrt::Windows::Foundation::IInspectable>>' being compiled
1>Done building project "BlankCppWinRT.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Это код XAML:

<Page
    x:Class="BlankCppWinRT.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:BlankCppWinRT"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" Loaded="OnLoaded">

    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
        <Button Margin="8" Width="160" x:Name="myButton" Click="ClickHandler">Click Me</Button>
        <ComboBox Margin="8" Width="160" x:Name="myComboBox" ItemsSource="{x:Bind Path=BoxItems}" SelectedItem="{x:Bind Path=SelectedBoxItem, Mode=TwoWay}"/>
    </StackPanel>
</Page>

Это мой файл IDL:

namespace BlankCppWinRT
{
    [bindable]
    [default_interface]
    runtimeclass MainPage : Windows.UI.Xaml.Controls.Page, Windows.UI.Xaml.Data.INotifyPropertyChanged
    {
        MainPage();
        Windows.Foundation.Collections.IObservableVector<String> BoxItems{get;};
        String SelectedBoxItem;
        protected void RaisePropertyChanged(String propertyName);
    }
}

Это мой MainPage.h:

#pragma once

#include "MainPage.g.h"

namespace winrt::BlankCppWinRT::implementation
{
    struct MainPage : MainPageT<MainPage>
    {
        MainPage();

        Windows::Foundation::Collections::IObservableVector<hstring> BoxItems();
        hstring SelectedBoxItem();
        void SelectedBoxItem(hstring const& value);

        void ClickHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args);

        void RaisePropertyChanged(hstring const& propertyName);
        winrt::event_token PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler);
        void PropertyChanged(winrt::event_token const& token) noexcept;

    protected:
        template<typename T>
        bool SetProperty(T& storage, const T& value, const hstring& propertyName)
        {
            if (storage == value)
                return false;
            storage = value;
            RaisePropertyChanged(propertyName);
            return true;
        }

    private:
        event<winrt::Windows::UI::Xaml::Data::PropertyChangedEventHandler> m_propertyChanged;

    private:
        Windows::Foundation::Collections::IObservableVector<hstring> m_boxItems;
        hstring m_selectedBoxItem;
    };
}

namespace winrt::BlankCppWinRT::factory_implementation
{
    struct MainPage : MainPageT<MainPage, implementation::MainPage>
    {
    };
}

1 Ответ

0 голосов
/ 11 февраля 2020

Добавление конвертера как Faywang - MSFT предлагаемые работы. Больше нет ошибки компиляции, и двусторонняя привязка обновляет свойство SelectedItem ComboBox.

Тем не менее, я нахожу странным, что мне приходится делать это в C ++ / WinRT, пока это работает коробки без конвертера в C ++ / CX и C#. Более того, проблемы, описанные в C ++ WinRT UWP XAML Привязка данных ItemsSource и SelectedIndex к IObservableVector не работает , остается. При изменении SelectedItem, например, в обработчике события Clicked кнопки генерируются исключения, а в некоторых случаях ComboBox отображает пустую запись.

Это код XAML:

<Page
    x:Class="BlankAppCppWinRT.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:BlankAppCppWinRT"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <Page.Resources>
        <local:SelectedItemConverter x:Key="SelectedItemConverter"/>
    </Page.Resources>

    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
        <Button Width="80" Margin="8" Click="OnNextButtonClicked">Next</Button>
        <ComboBox Width="80" Margin="8" x:Name="boxItemsComboBox" ItemsSource="{x:Bind Path=ViewModel.BoxItems}" SelectedItem="{x:Bind Path=ViewModel.SelectedBoxItem, Mode=TwoWay, Converter={StaticResource SelectedItemConverter}}"/>
    </StackPanel>
</Page>

Это файл IDL из SelectedItemConverter:

namespace BlankAppCppWinRT
{
    runtimeclass SelectedItemConverter : [default] Windows.UI.Xaml.Data.IValueConverter
    {
        SelectedItemConverter();
    }
}

И реализация:

#pragma once

#include "SelectedItemConverter.g.h"

namespace winrt::BlankAppCppWinRT::implementation
{
    struct SelectedItemConverter : SelectedItemConverterT<SelectedItemConverter>
    {
        SelectedItemConverter() = default;

        Windows::Foundation::IInspectable Convert(Windows::Foundation::IInspectable const& value, Windows::UI::Xaml::Interop::TypeName const& targetType, Windows::Foundation::IInspectable const& parameter, hstring const& language);
        Windows::Foundation::IInspectable ConvertBack(Windows::Foundation::IInspectable const& value, Windows::UI::Xaml::Interop::TypeName const& targetType, Windows::Foundation::IInspectable const& parameter, hstring const& language);
    };
}

namespace winrt::BlankAppCppWinRT::factory_implementation
{
    struct SelectedItemConverter : SelectedItemConverterT<SelectedItemConverter, implementation::SelectedItemConverter>
    {
    };
}

#include "pch.h"
#include "SelectedItemConverter.h"
#if __has_include("SelectedItemConverter.g.cpp")
#include "SelectedItemConverter.g.cpp"
#endif

namespace winrt::BlankAppCppWinRT::implementation
{
    Windows::Foundation::IInspectable SelectedItemConverter::Convert(Windows::Foundation::IInspectable const& value, Windows::UI::Xaml::Interop::TypeName const& /*targetType*/, Windows::Foundation::IInspectable const& /*parameter*/, hstring const& /*language*/)
    {
        return value;
    }

    Windows::Foundation::IInspectable SelectedItemConverter::ConvertBack(Windows::Foundation::IInspectable const& value, Windows::UI::Xaml::Interop::TypeName const& /*targetType*/, Windows::Foundation::IInspectable const& /*parameter*/, hstring const& /*language*/)
    {
        return value;
    }
}

...