C ++ WinRT UWP XAML数据将ItemsSource和SelectedIndex绑定到IObservableVector< hstring>不起作用 [英] C++ WinRT UWP XAML Data binding ItemsSource and SelectedIndex to IObservableVector<hstring> does not work

查看:124
本文介绍了C ++ WinRT UWP XAML数据将ItemsSource和SelectedIndex绑定到IObservableVector< hstring>不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Visual Studio 2019 16.4.3,Microsoft.Windows.CppWinRT 2.0.200117.5,Windows 10 1809 Pro和目标10.0.17763.0。

I am using Visual Studio 2019 16.4.3, Microsoft.Windows.CppWinRT 2.0.200117.5, Windows 10 1809 Pro and targeting 10.0.17763.0.

我正在尝试将C ++ / CX应用移植到C ++ WinRT。我正在使用 ItemsSource SelectedIndex SelectedItem 组合框的属性,但是我遇到了问题。

I am trying to port a C++/CX app to C++ WinRT. I am using data binding of the ItemsSource, SelectedIndexand SelectedItem properties of a combo box but I am running into issues.

对于 ItemsSource 我绑定到 IObservableVector< String> 。该属性使用 IObservableVector< hstring> 实现,并使用 single_threaded_observable_vector(std :: vector< hstring>({{L One,L Two ,L Three})))

For the ItemsSource I am binding to a IObservableVector<String>. The property is implemented using IObservableVector<hstring> and initialized with single_threaded_observable_vector(std::vector<hstring>({L"One", L"Two", L"Three"}))

启动应用程序时,出现以下异常:

When starting the application I am getting the following exception:

在BlankCppWinRT.exe中的0x766B19B2处引发的异常:Microsoft C ++异常:内存位置0x03AED210的winrt :: hresult_no_interface。发生

Exception thrown at 0x766B19B2 in BlankCppWinRT.exe: Microsoft C++ exception: winrt::hresult_no_interface at memory location 0x03AED210. occurred

这应该起作用吗?如何将 ItemsSource 绑定到字符串集合?这适用于C#和C ++ / CX。 C ++ WinRT中的等效项是什么?

Is this supposed to work? How do I data bind a ItemsSource to a collection of strings? This works in C# and C++/CX. What is the equivalent in C++ WinRT?

当我删除与 SelectedIndex 的双向绑定时,应用程序启动并显示组合框中的三个字符串,其中包含一个空的选定项目。但是,当我尝试通过 myComboBox()。SelectedIndex(0); (在构造函数中)在代码中设置所选索引时,我遇到了相同的异常。而同一行在页面的 Loaded 处理程序中起作用。

When I remove the two way binding to SelectedIndex the application starts and shows the three strings in the combo box, with an empty selected item. But when I try to set the selected index in code by myComboBox().SelectedIndex(0); (in the constructor) I am getting the same exception. Whereas the same line works in the Loaded handler of the page.

下面的详细信息。

有什么想法吗?

调用堆栈例外:

    KernelBase.dll!_RaiseException@16() Unknown
    vcruntime140d_app.dll!_CxxThrowException(void * pExceptionObject, const _s__ThrowInfo * pThrowInfo) Line 133    C++
>   BlankCppWinRT.exe!winrt::throw_hresult(const winrt::hresult result) Line 4623   C++
    BlankCppWinRT.exe!winrt::check_hresult(const winrt::hresult result) Line 4700   C++
    BlankCppWinRT.exe!winrt::impl::as<winrt::Windows::Foundation::IReference<winrt::hstring>,winrt::impl::abi<winrt::Windows::Foundation::IUnknown,void>::type>(winrt::impl::abi<winrt::Windows::Foundation::IUnknown,void>::type * ptr) Line 1941  C++
    BlankCppWinRT.exe!winrt::Windows::Foundation::IUnknown::as<winrt::Windows::Foundation::IReference<winrt::hstring>>() Line 2026  C++
    BlankCppWinRT.exe!winrt::unbox_value<winrt::hstring>(const winrt::Windows::Foundation::IInspectable & value) Line 2872  C++
    BlankCppWinRT.exe!winrt::impl::convertible_observable_vector<winrt::hstring,std::vector<winrt::hstring,std::allocator<winrt::hstring>>>::IndexOf(const winrt::Windows::Foundation::IInspectable & value, unsigned int & index) Line 2547    C++
    BlankCppWinRT.exe!winrt::impl::produce<winrt::impl::convertible_observable_vector<winrt::hstring,std::vector<winrt::hstring,std::allocator<winrt::hstring>>>,winrt::Windows::Foundation::Collections::IVector<winrt::Windows::Foundation::IInspectable>>::IndexOf(void * value, unsigned int * index, bool * winrt_impl_result) Line 566    C++
    Windows.UI.Xaml.dll!DirectUI::ItemCollection::IndexOf(IInspectable * value, unsigned int * index, unsigned char * found) Line 139   C++
    Windows.UI.Xaml.dll!DirectUI::ItemsControl::IsHostForItemContainer(Windows::UI::Xaml::IDependencyObject * pContainer, unsigned char * pIsHost) Line 1939    C++
    Windows.UI.Xaml.dll!DirectUI::ComboBox::IsHostForItemContainer(Windows::UI::Xaml::IDependencyObject * pContainer, unsigned char * pIsHost) Line 1239    C++
    Windows.UI.Xaml.dll!DirectUI::ItemContainerGenerator::ItemFromContainerImpl(Windows::UI::Xaml::IDependencyObject * container, IInspectable * * returnValue) Line 767    C++
    Windows.UI.Xaml.dll!DirectUI::ItemContainerGeneratorGenerated::ItemFromContainer(Windows::UI::Xaml::IDependencyObject * pContainer, IInspectable * * ppReturnValue) Line 222    C++

这是我的XAML代码:

This is my XAML code:

<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}" SelectedIndex="{x:Bind Path=SelectedBoxItemIndex, 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;};
        Int32 SelectedBoxItemIndex;
        protected void RaisePropertyChanged(String propertyName);
    }
}

此MainPage.h:

This MainPage.h:

#pragma once

#include "MainPage.g.h"

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

        Windows::Foundation::Collections::IObservableVector<hstring> BoxItems();

        int32_t SelectedBoxItemIndex();
        void SelectedBoxItemIndex(int32_t 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;

        void OnLoaded(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);

    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;
        int m_selectedBoxItemIndex{};
    };
}

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

这是MainPage.cpp:

This is MainPage.cpp:

#include "pch.h"
#include "MainPage.h"
#include "MainPage.g.cpp"

using namespace winrt;
using namespace Windows::UI::Xaml;

namespace winrt::BlankCppWinRT::implementation
{
    MainPage::MainPage()
        : m_boxItems{single_threaded_observable_vector(std::vector<hstring>({L"One", L"Two", L"Three"}))}
    {
        InitializeComponent();
        //causes exception
        //myComboBox().SelectedIndex(0);
    }

    Windows::Foundation::Collections::IObservableVector<hstring> MainPage::BoxItems()
    {
        return m_boxItems;
    }

    int32_t MainPage::SelectedBoxItemIndex()
    {
        return m_selectedBoxItemIndex;
    }

    // data binding to SelectedBoxItemIndex causes exception

    void MainPage::SelectedBoxItemIndex(int32_t value)
    {
        SetProperty(m_selectedBoxItemIndex, value, L"SelectedBoxItemIndex");
    }

    void MainPage::ClickHandler(IInspectable const&, RoutedEventArgs const&)
    {
        myButton().Content(box_value(L"Clicked"));
        SelectedBoxItemIndex(2);
    }

    void MainPage::RaisePropertyChanged(hstring const& propertyName)
    {
        m_propertyChanged(*this, PropertyChangedEventArgs(propertyName));
    }

    winrt::event_token MainPage::PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler)
    {
        return m_propertyChanged.add(handler);
    }

    void MainPage::PropertyChanged(winrt::event_token const& token) noexcept
    {
        m_propertyChanged.remove(token);
    }

    void MainPage::OnLoaded(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e)
    {
        // works
        myComboBox().SelectedIndex(0);
    }
}


推荐答案

作为权宜之计,您可以转到Windows.Foundation.Collections.h以覆盖IndexOf()方法。当unbox_value失败时,捕获hresult_no_interface异常并返回false。有关更多详细信息,您可以参考此线程

As a stopgap fix, you could go to the Windows.Foundation.Collections.h to override the IndexOf() method. When unbox_value fails, catch the hresult_no_interface exception and return false. For more details, you can refer to this thread.

bool IndexOf(Windows::Foundation::IInspectable const& value, uint32_t& index) const
{
    //return IndexOf(unbox_value<T>(value), index);
    try
    {
        return IndexOf(unbox_value<T>(value), index);
    }
    catch (hresult_no_interface const&)
    {
        return false; // unbox_value failed, "value" wasn't even a boxed T
    }
}

这篇关于C ++ WinRT UWP XAML数据将ItemsSource和SelectedIndex绑定到IObservableVector&lt; hstring&gt;不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆