次の方法で共有


winrt::single_threaded_observable_vector 関数テンプレート (C++/WinRT)

監視可能なコレクションを実装する型のオブジェクトを作成して返す関数テンプレート。 オブジェクトは IObservableVectorとして返されます。これは、返されたオブジェクトの関数とプロパティを呼び出すインターフェイスです。

必要に応じて、既存の std::vector右辺値 を関数に渡すことができます。一時オブジェクトを渡すか、左辺値で std::move 呼び出します。

詳細とコード例については、「C++/WinRTを使用したコレクションの 」を参照してください。

構文

template <typename T, typename Allocator = std::allocator<T>>
winrt::Windows::Foundation::Collections::IObservableVector<T> single_threaded_observable_vector(std::vector<T, Allocator>&& values = {})

テンプレート パラメーター

typename T コレクションの要素の型。

typename Allocator コレクションを初期化するベクターのアロケーターの型 (渡す場合)、それ以外の場合は既定のアロケーター。

パラメーター

コレクション オブジェクトの要素を初期化する std::vector 型の 右辺値 への省略可能な参照。

戻り値

IObservableVector 新しいコレクション オブジェクトを表します。

必要条件

サポートされている最小 SDK: Windows SDK バージョン 10.0.17763.0 (Windows 10 バージョン 1809) を

Namespace: winrt

ヘッダー: %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt\base.h (既定で含まれます)

古いバージョンの Windows SDK をお持ちの場合

Windows SDK バージョン 10.0.17763.0 (Windows 10 バージョン 1809) 以降がない場合は、独自の監視可能なベクター テンプレートを実装して、IObservableVector<T>の便利な汎用実装として機能する必要があります。 次に、single_threaded_observable_vector<T>というクラスの一覧を示します。 以下の種類から winrt::single_threaded_observable_vector を に切り替えるには、それが含まれる Windows SDK のバージョンを使用している場合に簡単に切り替えることができます。

// single_threaded_observable_vector.h
#pragma once

namespace winrt::Bookstore::implementation
{
    using namespace Windows::Foundation::Collections;

    template <typename T>
    struct single_threaded_observable_vector : implements<single_threaded_observable_vector<T>,
        IObservableVector<T>,
        IVector<T>,
        IVectorView<T>,
        IIterable<T>>
    {
        event_token VectorChanged(VectorChangedEventHandler<T> const& handler)
        {
            return m_changed.add(handler);
        }

        void VectorChanged(event_token const cookie)
        {
            m_changed.remove(cookie);
        }

        T GetAt(uint32_t const index) const
        {
            if (index >= m_values.size())
            {
                throw hresult_out_of_bounds();
            }

            return m_values[index];
        }

        uint32_t Size() const noexcept
        {
            return static_cast<uint32_t>(m_values.size());
        }

        IVectorView<T> GetView()
        {
            return *this;
        }

        bool IndexOf(T const& value, uint32_t& index) const noexcept
        {
            index = static_cast<uint32_t>(std::find(m_values.begin(), m_values.end(), value) - m_values.begin());
            return index < m_values.size();
        }

        void SetAt(uint32_t const index, T const& value)
        {
            if (index >= m_values.size())
            {
                throw hresult_out_of_bounds();
            }

            ++m_version;
            m_values[index] = value;
            m_changed(*this, make<args>(CollectionChange::ItemChanged, index));
        }

        void InsertAt(uint32_t const index, T const& value)
        {
            if (index > m_values.size())
            {
                throw hresult_out_of_bounds();
            }

            ++m_version;
            m_values.insert(m_values.begin() + index, value);
            m_changed(*this, make<args>(CollectionChange::ItemInserted, index));
        }

        void RemoveAt(uint32_t const index)
        {
            if (index >= m_values.size())
            {
                throw hresult_out_of_bounds();
            }

            ++m_version;
            m_values.erase(m_values.begin() + index);
            m_changed(*this, make<args>(CollectionChange::ItemRemoved, index));
        }

        void Append(T const& value)
        {
            ++m_version;
            m_values.push_back(value);
            m_changed(*this, make<args>(CollectionChange::ItemInserted, Size() - 1));
        }

        void RemoveAtEnd()
        {
            if (m_values.empty())
            {
                throw hresult_out_of_bounds();
            }

            ++m_version;
            m_values.pop_back();
            m_changed(*this, make<args>(CollectionChange::ItemRemoved, Size()));
        }

        void Clear() noexcept
        {
            ++m_version;
            m_values.clear();
            m_changed(*this, make<args>(CollectionChange::Reset, 0));
        }

        uint32_t GetMany(uint32_t const startIndex, array_view<T> values) const
        {
            if (startIndex >= m_values.size())
            {
                return 0;
            }

            uint32_t actual = static_cast<uint32_t>(m_values.size() - startIndex);

            if (actual > values.size())
            {
                actual = values.size();
            }

            std::copy_n(m_values.begin() + startIndex, actual, values.begin());
            return actual;
        }

        void ReplaceAll(array_view<T const> value)
        {
            ++m_version;
            m_values.assign(value.begin(), value.end());
            m_changed(*this, make<args>(CollectionChange::Reset, 0));
        }

        IIterator<T> First()
        {
            return make<iterator>(this);
        }

    private:

        std::vector<T> m_values;
        event<VectorChangedEventHandler<T>> m_changed;
        uint32_t m_version{};

        struct args : implements<args, IVectorChangedEventArgs>
        {
            args(CollectionChange const change, uint32_t const index) :
                m_change(change),
                m_index(index)
            {
            }

            CollectionChange CollectionChange() const
            {
                return m_change;
            }

            uint32_t Index() const
            {
                return m_index;
            }

        private:

            Windows::Foundation::Collections::CollectionChange const m_change{};
            uint32_t const m_index{};
        };

        struct iterator : implements<iterator, IIterator<T>>
        {
            explicit iterator(single_threaded_observable_vector<T>* owner) noexcept :
            m_version(owner->m_version),
                m_current(owner->m_values.begin()),
                m_end(owner->m_values.end())
            {
                m_owner.copy_from(owner);
            }

            void abi_enter() const
            {
                if (m_version != m_owner->m_version)
                {
                    throw hresult_changed_state();
                }
            }

            T Current() const
            {
                if (m_current == m_end)
                {
                    throw hresult_out_of_bounds();
                }

                return*m_current;
            }

            bool HasCurrent() const noexcept
            {
                return m_current != m_end;
            }

            bool MoveNext() noexcept
            {
                if (m_current != m_end)
                {
                    ++m_current;
                }

                return HasCurrent();
            }

            uint32_t GetMany(array_view<T> values)
            {
                uint32_t actual = static_cast<uint32_t>(std::distance(m_current, m_end));

                if (actual > values.size())
                {
                    actual = values.size();
                }

                std::copy_n(m_current, actual, values.begin());
                std::advance(m_current, actual);
                return actual;
            }

        private:

            com_ptr<single_threaded_observable_vector<T>> m_owner;
            uint32_t const m_version;
            typename std::vector<T>::const_iterator m_current;
            typename std::vector<T>::const_iterator const m_end;
        };
    };
}

Append 関数は、IObservableVector<T>::VectorChanged イベントを発生させる方法を示しています。

m_changed(*this, make<args>(CollectionChange::ItemInserted, Size() - 1));

イベント引数は、要素が挿入されたことと、そのインデックス (この場合は最後の要素) の両方を示します。 これらの引数を使用すると、XAML 項目コントロールがイベントに応答し、最適な方法で自身を更新できます。

これは、上記で定義した型のインスタンスを作成する方法です。 winrt::single_threaded_observable_vector ファクトリ関数テンプレートを呼び出す代わりに、winrt::make呼び出してコレクション オブジェクトを作成します。

#include "single_threaded_observable_vector.h"
...
winrt::Windows::Foundation::Collections::IVector<winrt::Windows::Foundation::IInspectable> m_bookSkus;
...
m_bookSkus = winrt::make<winrt::Bookstore::implementation::single_threaded_observable_vector<winrt::Windows::Foundation::IInspectable>>();

関連項目