// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #pragma once namespace CalculatorApp { namespace Common { ref class AlwaysSelectedCollectionView sealed: public Windows::UI::Xaml::DependencyObject, public Windows::UI::Xaml::Data::ICollectionView { internal: AlwaysSelectedCollectionView(Windows::UI::Xaml::Interop::IBindableVector^ source): m_currentPosition(-1) { m_source = source; Windows::UI::Xaml::Interop::IBindableObservableVector^ observable = dynamic_cast(source); if (observable) { observable->VectorChanged += ref new Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler(this, &AlwaysSelectedCollectionView::OnSourceBindableVectorChanged); } } private: // ICollectionView // Not implemented methods virtual WF::IAsyncOperation^ LoadMoreItemsAsync(unsigned int) = Windows::UI::Xaml::Data::ICollectionView::LoadMoreItemsAsync { throw ref new Platform::NotImplementedException(); } virtual bool MoveCurrentToFirst() = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToFirst { throw ref new Platform::NotImplementedException(); } virtual bool MoveCurrentToLast() = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToLast { throw ref new Platform::NotImplementedException(); } virtual bool MoveCurrentToNext() = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToNext { throw ref new Platform::NotImplementedException(); } virtual bool MoveCurrentToPrevious() = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToPrevious { throw ref new Platform::NotImplementedException(); } property Windows::Foundation::Collections::IObservableVector^ CollectionGroups { virtual Windows::Foundation::Collections::IObservableVector^ get() = Windows::UI::Xaml::Data::ICollectionView::CollectionGroups::get { return ref new Platform::Collections::Vector(); } } property bool HasMoreItems { virtual bool get() = Windows::UI::Xaml::Data::ICollectionView::HasMoreItems::get { return false; } } // Implemented methods virtual bool MoveCurrentTo(Platform::Object^ item) = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentTo { if (item) { unsigned int newCurrentPosition = 0; bool result = m_source->IndexOf(item, &newCurrentPosition); if (result) { m_currentPosition = newCurrentPosition; m_currentChanged(this, nullptr); return true; } } // The item is not in the collection // We're going to schedule a call back later so we // restore the selection to the way we wanted it to begin with if (m_currentPosition >= 0 && m_currentPosition < static_cast(m_source->Size)) { this->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, ref new Windows::UI::Core::DispatchedHandler( [this]() { m_currentChanged(this, nullptr); })); } return false; } virtual bool MoveCurrentToPosition(int index) = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentToPosition { if (index < 0 || index >= static_cast(m_source->Size)) { return false; } m_currentPosition = index; m_currentChanged(this, nullptr); return true; } property Platform::Object^ CurrentItem { virtual Platform::Object^ get() = Windows::UI::Xaml::Data::ICollectionView::CurrentItem::get { if (m_currentPosition >= 0 && m_currentPosition < static_cast(m_source->Size)) { return m_source->GetAt(m_currentPosition); } return nullptr; } } property int CurrentPosition { virtual int get() = Windows::UI::Xaml::Data::ICollectionView::CurrentPosition::get { return m_currentPosition; } } property bool IsCurrentAfterLast { virtual bool get() = Windows::UI::Xaml::Data::ICollectionView::IsCurrentAfterLast::get { return m_currentPosition >= static_cast(m_source->Size); } } property bool IsCurrentBeforeFirst { virtual bool get() = Windows::UI::Xaml::Data::ICollectionView::IsCurrentBeforeFirst::get { return m_currentPosition < 0; } } event WF::EventHandler^ CurrentChanged { virtual WF::EventRegistrationToken add(WF::EventHandler^ handler) = Windows::UI::Xaml::Data::ICollectionView::CurrentChanged::add { return m_currentChanged += handler; } virtual void remove(WF::EventRegistrationToken token) = Windows::UI::Xaml::Data::ICollectionView::CurrentChanged::remove { m_currentChanged -= token; } } event Windows::UI::Xaml::Data::CurrentChangingEventHandler^ CurrentChanging { virtual WF::EventRegistrationToken add(Windows::UI::Xaml::Data::CurrentChangingEventHandler^ handler) = Windows::UI::Xaml::Data::ICollectionView::CurrentChanging::add { return m_currentChanging += handler; } virtual void remove(WF::EventRegistrationToken token) = Windows::UI::Xaml::Data::ICollectionView::CurrentChanging::remove { m_currentChanging -= token; } } // IVector // Not implemented methods virtual void Append(Platform::Object^ /*item*/) = Windows::Foundation::Collections::IVector::Append { throw ref new Platform::NotImplementedException(); } virtual void Clear() = Windows::Foundation::Collections::IVector::Clear { throw ref new Platform::NotImplementedException(); } virtual unsigned int GetMany(unsigned int /*startIndex*/, Platform::WriteOnlyArray^ /*items*/) = Windows::Foundation::Collections::IVector::GetMany { throw ref new Platform::NotImplementedException(); } virtual Windows::Foundation::Collections::IVectorView^ GetView() = Windows::Foundation::Collections::IVector::GetView { throw ref new Platform::NotImplementedException(); } virtual void InsertAt(unsigned int /*index*/, Platform::Object^ /*item*/) = Windows::Foundation::Collections::IVector::InsertAt { throw ref new Platform::NotImplementedException(); } virtual void RemoveAt(unsigned int /*index*/) = Windows::Foundation::Collections::IVector::RemoveAt { throw ref new Platform::NotImplementedException(); } virtual void RemoveAtEnd() = Windows::Foundation::Collections::IVector::RemoveAtEnd { throw ref new Platform::NotImplementedException(); } virtual void ReplaceAll(const Platform::Array^ /*items*/) = Windows::Foundation::Collections::IVector::ReplaceAll { throw ref new Platform::NotImplementedException(); } virtual void SetAt(unsigned int /*index*/, Platform::Object^ /*item*/) = Windows::Foundation::Collections::IVector::SetAt { throw ref new Platform::NotImplementedException(); } // Implemented methods virtual Platform::Object^ GetAt(unsigned int index) = Windows::Foundation::Collections::IVector::GetAt { return m_source->GetAt(index); } virtual bool IndexOf(Platform::Object^ item, unsigned int* index) = Windows::Foundation::Collections::IVector::IndexOf { return m_source->IndexOf(item, index); } property unsigned int Size { virtual unsigned int get() = Windows::Foundation::Collections::IVector::Size::get { return m_source->Size; } } // IObservableVector event Windows::Foundation::Collections::VectorChangedEventHandler^ VectorChanged { virtual WF::EventRegistrationToken add(Windows::Foundation::Collections::VectorChangedEventHandler^ handler) = Windows::Foundation::Collections::IObservableVector::VectorChanged::add { return m_vectorChanged += handler; } virtual void remove(WF::EventRegistrationToken token) = Windows::Foundation::Collections::IObservableVector::VectorChanged::remove { m_vectorChanged -= token; } } // IIterable // Not implemented virtual Windows::Foundation::Collections::IIterator^ First() = Windows::Foundation::Collections::IIterable::First { throw ref new Platform::NotImplementedException(); } // Event handlers void OnSourceBindableVectorChanged(Windows::UI::Xaml::Interop::IBindableObservableVector^ source, Platform::Object^ e) { Windows::Foundation::Collections::IVectorChangedEventArgs^ args = safe_cast(e); m_vectorChanged(this, args); } Windows::UI::Xaml::Interop::IBindableVector^ m_source; int m_currentPosition; event WF::EventHandler^ m_currentChanged; event Windows::UI::Xaml::Data::CurrentChangingEventHandler^ m_currentChanging; event Windows::Foundation::Collections::VectorChangedEventHandler^ m_vectorChanged; }; public ref class AlwaysSelectedCollectionViewConverter sealed: public Windows::UI::Xaml::Data::IValueConverter { public: AlwaysSelectedCollectionViewConverter() { } private: virtual Platform::Object^ Convert( Platform::Object^ value, Windows::UI::Xaml::Interop::TypeName /*targetType*/, Platform::Object^ /*parameter*/, Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::Convert { auto result = dynamic_cast(value); if (result) { return ref new AlwaysSelectedCollectionView(result); } return Windows::UI::Xaml::DependencyProperty::UnsetValue; // Can't convert } virtual Platform::Object^ ConverBack( Platform::Object^ /*value*/, Windows::UI::Xaml::Interop::TypeName /*targetType*/, Platform::Object^ /*parameter*/, Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack { return Windows::UI::Xaml::DependencyProperty::UnsetValue; } }; }}