#include "NavMenuListView.h" using namespace Platform; using namespace Windows::Foundation; using namespace Windows::Foundation::Collections; using namespace Windows::System; using namespace Windows::UI::Core; using namespace Windows::UI::Xaml; using namespace Windows::UI::Xaml::Controls; using namespace Windows::UI::Xaml::Data; using namespace Windows::UI::Xaml::Documents; using namespace Windows::UI::Xaml::Input; using namespace Windows::UI::Xaml::Interop; using namespace Windows::UI::Xaml::Media; using namespace Windows::UI::Xaml::Media::Animation; namespace VBA10 { namespace Controls { NavMenuListView::NavMenuListView() { this->SelectionMode = ListViewSelectionMode::Single; this->IsItemClickEnabled = true; this->ItemClick += ref new ItemClickEventHandler(this, &NavMenuListView::ItemClickHandler); // Locate the hosting SplitView control this->Loaded += ref new Windows::UI::Xaml::RoutedEventHandler(this, &VBA10::Controls::NavMenuListView::OnLoaded); } void NavMenuListView::OnLoaded(Platform::Object ^sender, Windows::UI::Xaml::RoutedEventArgs ^e) { auto parent = VisualTreeHelper::GetParent(this); while (parent != nullptr && dynamic_cast(parent) == nullptr) { parent = VisualTreeHelper::GetParent((DependencyObject^)parent); } if (parent != nullptr) { _splitViewHost = dynamic_cast(parent); _splitViewHost->RegisterPropertyChangedCallback( SplitView::IsPaneOpenProperty, ref new DependencyPropertyChangedCallback(this, &NavMenuListView::IsOpenPanePropertyChangedCallback)); // Call once to ensure we're in the correct state OnPaneToggled(); } } void NavMenuListView::IsOpenPanePropertyChangedCallback(DependencyObject^ sender, DependencyProperty^ args) { OnPaneToggled(); } void NavMenuListView::OnApplyTemplate() { ListView::OnApplyTemplate(); // Remove the entrance animation on the item containers. for (int i = 0; i < (int)ItemContainerTransitions->Size; i++) { if (dynamic_cast(ItemContainerTransitions->GetAt(i)) != nullptr) { ItemContainerTransitions->RemoveAt(i); } } } ///// ///// Custom keyboarding logic to enable movement via the arrow keys without triggering selection ///// until a 'Space' or 'Enter' key is pressed. ///// ///// //void NavMenuListView::OnKeyDown(KeyRoutedEventArgs^ e) //{ // auto focusedItem = FocusManager::GetFocusedElement(); // auto shiftKeyState = CoreWindow::GetForCurrentThread()->GetKeyState(VirtualKey::Shift); // auto shiftKeyDown = (shiftKeyState & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down; // switch (e->Key) // { // case VirtualKey::Up: // this->TryMoveFocus(FocusNavigationDirection::Up); // e->Handled = true; // break; // case VirtualKey::Down: // this->TryMoveFocus(FocusNavigationDirection::Down); // e->Handled = true; // break; // case VirtualKey::Tab: // // If we're on the header item then this will be null and we'll still get the default behavior. // if (dynamic_cast(focusedItem) != nullptr) // { // auto currentItem = (ListViewItem^)focusedItem; // bool onlastitem = currentItem != nullptr && IndexFromContainer(currentItem) == Items->Size - 1; // bool onfirstitem = currentItem != nullptr && IndexFromContainer(currentItem) == 0; // if (!shiftKeyDown) // { // if (onlastitem) // { // this->TryMoveFocus(FocusNavigationDirection::Next); // } // else // { // this->TryMoveFocus(FocusNavigationDirection::Down); // } // } // else // Shift + Tab // { // if (onfirstitem) // { // this->TryMoveFocus(FocusNavigationDirection::Previous); // } // else // { // this->TryMoveFocus(FocusNavigationDirection::Up); // } // } // } // else if (dynamic_cast(focusedItem) != nullptr) // { // if (!shiftKeyDown) // { // this->TryMoveFocus(FocusNavigationDirection::Down); // } // else // Shift + Tab // { // this->TryMoveFocus(FocusNavigationDirection::Up); // } // } // e->Handled = true; // break; // case VirtualKey::Space: // case VirtualKey::Enter: // // Fire our event using the item with current keyboard focus // InvokeItem(focusedItem); // e->Handled = true; // break; // default: // ListView::OnKeyDown(e); // break; // } //} /// /// This method is a work-around until the bug in FocusManager.TryMoveFocus is fixed. /// /// //void NavMenuListView::TryMoveFocus(FocusNavigationDirection direction) //{ // if (direction == FocusNavigationDirection::Next || direction == FocusNavigationDirection::Previous) // { // FocusManager::TryMoveFocus(direction); // } // else // { // auto control = dynamic_cast(FocusManager::FindNextFocusableElement(direction)); // if (control != nullptr) // { // control->Focus(Windows::UI::Xaml::FocusState::Programmatic); // } // } //} void NavMenuListView::ItemClickHandler(Object^ sender, ItemClickEventArgs^ e) { // Triggered when the item is selected using something other than a keyboard auto item = ContainerFromItem(e->ClickedItem); InvokeItem(item); } void NavMenuListView::InvokeItem(Object^ focusedItem) { auto item = dynamic_cast(focusedItem); SetSelectedItem(item); ItemInvoked(this, item); //if (_splitViewHost->IsPaneOpen && ( // _splitViewHost->DisplayMode == SplitViewDisplayMode::CompactOverlay || // _splitViewHost->DisplayMode == SplitViewDisplayMode::Overlay)) //{ // _splitViewHost->IsPaneOpen = false; // if (item != nullptr) // { // item->Focus(Windows::UI::Xaml::FocusState::Programmatic); // } //} } /// /// Mark the as selected and ensures everything else is not. /// If the is null then everything is unselected. /// /// void NavMenuListView::SetSelectedItem(ListViewItem^ item) { int index = -1; if (item != nullptr) { index = IndexFromContainer(item); } for (int i = 0; i < (int)Items->Size; i++) { auto lvi = (ListViewItem^)ContainerFromIndex(i); if (lvi != nullptr) { if (i != index) { lvi->IsSelected = false; } else if (i == index) { lvi->IsSelected = true; } } } } /// /// Re-size the ListView's Panel when the SplitView is compact so the items /// will fit within the visible space and correctly display a keyboard focus rect. /// void NavMenuListView::OnPaneToggled() { if (_splitViewHost->IsPaneOpen) { ItemsPanelRoot->ClearValue(FrameworkElement::WidthProperty); ItemsPanelRoot->ClearValue(FrameworkElement::HorizontalAlignmentProperty); } else if (_splitViewHost->DisplayMode == SplitViewDisplayMode::CompactInline || _splitViewHost->DisplayMode == SplitViewDisplayMode::CompactOverlay) { ItemsPanelRoot->SetValue(FrameworkElement::WidthProperty, _splitViewHost->CompactPaneLength); ItemsPanelRoot->SetValue(FrameworkElement::HorizontalAlignmentProperty, Windows::UI::Xaml::HorizontalAlignment::Left); } } } }