Path: blob/master/samples/winrt/ImageManipulations/MainPage.xaml.cpp
16337 views
//*********************************************************1//2// Copyright (c) Microsoft. All rights reserved.3// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF4// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY5// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR6// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.7//8//*********************************************************910//11// MainPage.xaml.cpp12// Implementation of the MainPage.xaml class.13//1415#include "pch.h"16#include "MainPage.xaml.h"17#include "App.xaml.h"1819#include <collection.h>2021using namespace Windows::UI::Xaml;22using namespace Windows::UI::Xaml::Controls;23using namespace Windows::Foundation;24using namespace Windows::Foundation::Collections;25using namespace Platform;26using namespace SDKSample;27using namespace Windows::UI::Xaml::Navigation;28using namespace Windows::UI::Xaml::Interop;29using namespace Windows::Graphics::Display;30using namespace Windows::UI::ViewManagement;3132MainPage^ MainPage::Current = nullptr;3334MainPage::MainPage()35{36InitializeComponent();3738// This frame is hidden, meaning it is never shown. It is simply used to load39// each scenario page and then pluck out the input and output sections and40// place them into the UserControls on the main page.41HiddenFrame = ref new Windows::UI::Xaml::Controls::Frame();42HiddenFrame->Visibility = Windows::UI::Xaml::Visibility::Collapsed;43ContentRoot->Children->Append(HiddenFrame);4445FeatureName->Text = FEATURE_NAME;4647this->SizeChanged += ref new SizeChangedEventHandler(this, &MainPage::MainPage_SizeChanged);48Scenarios->SelectionChanged += ref new SelectionChangedEventHandler(this, &MainPage::Scenarios_SelectionChanged);4950MainPage::Current = this;51autoSizeInputSectionWhenSnapped = true;52}5354/// <summary>55/// We need to handle SizeChanged so that we can make the sample layout property56/// in the various layouts.57/// </summary>58/// <param name="sender"></param>59/// <param name="e"></param>60void MainPage::MainPage_SizeChanged(Object^ sender, SizeChangedEventArgs^ e)61{62InvalidateSize();63MainPageSizeChangedEventArgs^ args = ref new MainPageSizeChangedEventArgs();64args->ViewState = ApplicationView::Value;65MainPageResized(this, args);6667}6869void MainPage::InvalidateSize()70{71// Get the window width72double windowWidth = this->ActualWidth;7374if (windowWidth != 0.0)75{76// Get the width of the ListBox.77double listBoxWidth = Scenarios->ActualWidth;7879// Is the ListBox using any margins that we need to consider?80double listBoxMarginLeft = Scenarios->Margin.Left;81double listBoxMarginRight = Scenarios->Margin.Right;8283// Figure out how much room is left after considering the list box width84double availableWidth = windowWidth - listBoxWidth;8586// Is the top most child using margins?87double layoutRootMarginLeft = ContentRoot->Margin.Left;88double layoutRootMarginRight = ContentRoot->Margin.Right;8990// We have different widths to use depending on the view state91if (ApplicationView::Value != ApplicationViewState::Snapped)92{93// Make us as big as the the left over space, factoring in the ListBox width, the ListBox margins.94// and the LayoutRoot's margins95InputSection->Width = ((availableWidth) -96(layoutRootMarginLeft + layoutRootMarginRight + listBoxMarginLeft + listBoxMarginRight));97}98else99{100// Make us as big as the left over space, factoring in just the LayoutRoot's margins.101if (autoSizeInputSectionWhenSnapped)102{103InputSection->Width = (windowWidth - (layoutRootMarginLeft + layoutRootMarginRight));104}105}106}107InvalidateViewState();108}109110void MainPage::InvalidateViewState()111{112// Are we going to snapped mode?113if (ApplicationView::Value == ApplicationViewState::Snapped)114{115Grid::SetRow(DescriptionText, 3);116Grid::SetColumn(DescriptionText, 0);117118Grid::SetRow(InputSection, 4);119Grid::SetColumn(InputSection, 0);120121Grid::SetRow(FooterPanel, 2);122Grid::SetColumn(FooterPanel, 0);123}124else125{126Grid::SetRow(DescriptionText, 1);127Grid::SetColumn(DescriptionText, 1);128129Grid::SetRow(InputSection, 2);130Grid::SetColumn(InputSection, 1);131132Grid::SetRow(FooterPanel, 1);133Grid::SetColumn(FooterPanel, 1);134}135136// Since we don't load the scenario page in the traditional manner (we just pluck out the137// input and output sections from the page) we need to ensure that any VSM code used138// by the scenario's input and output sections is fired.139VisualStateManager::GoToState(InputSection, "Input" + LayoutAwarePage::DetermineVisualState(ApplicationView::Value), false);140VisualStateManager::GoToState(OutputSection, "Output" + LayoutAwarePage::DetermineVisualState(ApplicationView::Value), false);141}142143void MainPage::PopulateScenarios()144{145ScenarioList = ref new Platform::Collections::Vector<Object^>();146147// Populate the ListBox with the list of scenarios as defined in Constants.cpp.148for (unsigned int i = 0; i < scenarios->Length; ++i)149{150Scenario s = scenarios[i];151ListBoxItem^ item = ref new ListBoxItem();152item->Name = s.ClassName;153item->Content = (i + 1).ToString() + ") " + s.Title;154ScenarioList->Append(item);155}156157// Bind the ListBox to the scenario list.158Scenarios->ItemsSource = ScenarioList;159Scenarios->ScrollIntoView(Scenarios->SelectedItem);160}161162/// <summary>163/// This method is responsible for loading the individual input and output sections for each scenario. This164/// is based on navigating a hidden Frame to the ScenarioX.xaml page and then extracting out the input165/// and output sections into the respective UserControl on the main page.166/// </summary>167/// <param name="scenarioName"></param>168void MainPage::LoadScenario(String^ scenarioName)169{170autoSizeInputSectionWhenSnapped = true;171172// Load the ScenarioX.xaml file into the Frame.173TypeName scenarioType = {scenarioName, TypeKind::Custom};174HiddenFrame->Navigate(scenarioType, this);175176// Get the top element, the Page, so we can look up the elements177// that represent the input and output sections of the ScenarioX file.178Page^ hiddenPage = safe_cast<Page^>(HiddenFrame->Content);179180// Get each element.181UIElement^ input = safe_cast<UIElement^>(hiddenPage->FindName("Input"));182UIElement^ output = safe_cast<UIElement^>(hiddenPage->FindName("Output"));183184if (input == nullptr)185{186// Malformed input section.187NotifyUser("Cannot load scenario input section for " + scenarioName +188" Make sure root of input section markup has x:Name of 'Input'", NotifyType::ErrorMessage);189return;190}191192if (output == nullptr)193{194// Malformed output section.195NotifyUser("Cannot load scenario output section for " + scenarioName +196" Make sure root of output section markup has x:Name of 'Output'", NotifyType::ErrorMessage);197return;198}199200// Find the LayoutRoot which parents the input and output sections in the main page.201Panel^ panel = safe_cast<Panel^>(hiddenPage->FindName("LayoutRoot"));202203if (panel != nullptr)204{205unsigned int index = 0;206UIElementCollection^ collection = panel->Children;207208// Get rid of the content that is currently in the intput and output sections.209collection->IndexOf(input, &index);210collection->RemoveAt(index);211212collection->IndexOf(output, &index);213collection->RemoveAt(index);214215// Populate the input and output sections with the newly loaded content.216InputSection->Content = input;217OutputSection->Content = output;218219ScenarioLoaded(this, nullptr);220}221else222{223// Malformed Scenario file.224NotifyUser("Cannot load scenario: " + scenarioName + ". Make sure root tag in the '" +225scenarioName + "' file has an x:Name of 'LayoutRoot'", NotifyType::ErrorMessage);226}227}228229void MainPage::Scenarios_SelectionChanged(Object^ sender, SelectionChangedEventArgs^ e)230{231if (Scenarios->SelectedItem != nullptr)232{233NotifyUser("", NotifyType::StatusMessage);234235LoadScenario((safe_cast<ListBoxItem^>(Scenarios->SelectedItem))->Name);236InvalidateSize();237}238}239240void MainPage::NotifyUser(String^ strMessage, NotifyType type)241{242switch (type)243{244case NotifyType::StatusMessage:245// Use the status message style.246StatusBlock->Style = safe_cast<Windows::UI::Xaml::Style^>(this->Resources->Lookup("StatusStyle"));247break;248case NotifyType::ErrorMessage:249// Use the error message style.250StatusBlock->Style = safe_cast<Windows::UI::Xaml::Style^>(this->Resources->Lookup("ErrorStyle"));251break;252default:253break;254}255StatusBlock->Text = strMessage;256257// Collapsed the StatusBlock if it has no text to conserve real estate.258if (StatusBlock->Text != "")259{260StatusBlock->Visibility = Windows::UI::Xaml::Visibility::Visible;261}262else263{264StatusBlock->Visibility = Windows::UI::Xaml::Visibility::Collapsed;265}266}267268void MainPage::Footer_Click(Object^ sender, RoutedEventArgs^ e)269{270auto uri = ref new Uri((String^)((HyperlinkButton^)sender)->Tag);271Windows::System::Launcher::LaunchUriAsync(uri);272}273274275/// <summary>276/// Populates the page with content passed during navigation. Any saved state is also277/// provided when recreating a page from a prior session.278/// </summary>279/// <param name="navigationParameter">The parameter value passed to280/// <see cref="Frame::Navigate(Type, Object)"/> when this page was initially requested.281/// </param>282/// <param name="pageState">A map of state preserved by this page during an earlier283/// session. This will be null the first time a page is visited.</param>284void MainPage::LoadState(Object^ navigationParameter, IMap<String^, Object^>^ pageState)285{286(void) navigationParameter; // Unused parameter287288PopulateScenarios();289290// Starting scenario is the first or based upon a previous state.291ListBoxItem^ startingScenario = nullptr;292int startingScenarioIndex = -1;293294if (pageState != nullptr && pageState->HasKey("SelectedScenarioIndex"))295{296startingScenarioIndex = safe_cast<int>(pageState->Lookup("SelectedScenarioIndex"));297}298299Scenarios->SelectedIndex = startingScenarioIndex != -1 ? startingScenarioIndex : 0;300301InvalidateViewState();302}303304/// <summary>305/// Preserves state associated with this page in case the application is suspended or the306/// page is discarded from the navigation cache. Values must conform to the serialization307/// requirements of <see cref="SuspensionManager::SessionState"/>.308/// </summary>309/// <param name="pageState">An empty map to be populated with serializable state.</param>310void MainPage::SaveState(IMap<String^, Object^>^ pageState)311{312int selectedListBoxItemIndex = Scenarios->SelectedIndex;313pageState->Insert("SelectedScenarioIndex", selectedListBoxItemIndex);314}315316317