Приведение к шаблонным классам из объектов фреймворка в C++/Cx

В настоящее время я работаю над созданием нового контейнера в своем проекте WinRT. Этот контейнер будет вести себя аналогично ListView, поэтому я решил использовать аналогичные имена в его свойствах.

Я создал DependencyProperty для ItemsSource, чтобы имитировать встроенный ItemsControl (абстрактный родитель для других списков). ItemsControl определяет ItemsSource как Platform::Object^, поэтому я сделал то же самое. Это прекрасно работает.

Позже пришло время создать элементы для включения в список, заполнить их экземплярами указанного ItemsTemplate и установить их контексты данных. Это означает, что мне нужно преобразовать ItemsSource из Platform::Object^ во что-то итерируемое. К сожалению, чтобы привести его к чему-то итерируемому, мне нужно указать тип шаблона в приведении (например, IIterable<UIElement^>^ или IIterable<Object^>^). На данном этапе мне все равно, какой это тип объекта, потому что я просто использую его как DataContext для нового элемента списка, поэтому приведение к IIterable<Object^>^ было бы в порядке. К сожалению, safe_cast не позволяет мне сделать это, если вещь, изначально установленная в ItemsSource, также не была шаблонирована как IIterable<Object^>^ или какой-либо дочерний элемент, такой как IVectorView<Object^>^.

С существующими контейнерами, такими как ListView, вы можете установить для ItemsSource значение Vector<MyCustomViewModel^>^ без предварительного преобразования его в Vector<Object^>^, и это прекрасно работает. Итак, как они это делают? Они не используют safe_cast? Я почти уверен, что использование менее безопасного броска имело бы здесь неблагоприятные последствия. Есть другие идеи?

TL;DR:

У меня есть некоторая ссылка Platform::Object^, которая, как я знаю, указывает на IIterable других ссылок. Можно ли каким-то образом привести его к IIterable<Platform::Object^>^, даже если итерируемый объект изначально был создан с каким-то другим шаблоном (например, IIterable<MyCustomViewModel^>^)?


person Brent Traut    schedule 04.12.2012    source источник


Ответы (1)


Поскольку C++/CX не поддерживает совместную/контравариантность типов (Platform::Vector<T^> не реализует IVector<Object^>), команда Xaml добавила специальный неуниверсальный интерфейс Windows.UI.Xaml.Interop.IBindableObservableVector, который дает вам объектную коллекцию для итерации. Platform::Vector реализует этот интерфейс специально для решения проблемы, с которой вы боретесь. Таким образом, в вашем случае вы должны иметь возможность использовать этот специальный интерфейс.

Я не уверен, поддерживают ли коллекции .NET этот интерфейс, поэтому, чтобы ваш пользовательский элемент управления поддерживал C#/VB, вы можете выполнить dynamic_cast для IBindableObservableVector, и если результатом является nullptr, попробуйте выполнить приведение к другим типам коллекций (таким как IVector<Object^>).

person Andy Rich    schedule 06.12.2012
comment
В частности, интерфейс IBindableVector (от которого наследуется IBOV) обладает большей частью необходимой вам функциональности. - person Andy Rich; 06.12.2012