• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //*********************************************************
2 //
3 // Copyright (c) Microsoft. All rights reserved.
4 // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
5 // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
6 // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
7 // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
8 //
9 //*********************************************************
10 
11 //
12 // MainPage.xaml.cpp
13 // Implementation of the MainPage.xaml class.
14 //
15 
16 #include "pch.h"
17 #include "MainPage.xaml.h"
18 #include "App.xaml.h"
19 
20 #include <collection.h>
21 
22 using namespace Windows::UI::Xaml;
23 using namespace Windows::UI::Xaml::Controls;
24 using namespace Windows::Foundation;
25 using namespace Windows::Foundation::Collections;
26 using namespace Platform;
27 using namespace SDKSample;
28 using namespace Windows::UI::Xaml::Navigation;
29 using namespace Windows::UI::Xaml::Interop;
30 using namespace Windows::Graphics::Display;
31 using namespace Windows::UI::ViewManagement;
32 
33 MainPage^ MainPage::Current = nullptr;
34 
MainPage()35 MainPage::MainPage()
36 {
37     InitializeComponent();
38 
39     // This frame is hidden, meaning it is never shown.  It is simply used to load
40     // each scenario page and then pluck out the input and output sections and
41     // place them into the UserControls on the main page.
42     HiddenFrame = ref new Windows::UI::Xaml::Controls::Frame();
43     HiddenFrame->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
44     ContentRoot->Children->Append(HiddenFrame);
45 
46     FeatureName->Text = FEATURE_NAME;
47 
48     this->SizeChanged += ref new SizeChangedEventHandler(this, &MainPage::MainPage_SizeChanged);
49     Scenarios->SelectionChanged += ref new SelectionChangedEventHandler(this, &MainPage::Scenarios_SelectionChanged);
50 
51     MainPage::Current = this;
52     autoSizeInputSectionWhenSnapped = true;
53 }
54 
55 /// <summary>
56 /// We need to handle SizeChanged so that we can make the sample layout property
57 /// in the various layouts.
58 /// </summary>
59 /// <param name="sender"></param>
60 /// <param name="e"></param>
61 void MainPage::MainPage_SizeChanged(Object^ sender, SizeChangedEventArgs^ e)
62 {
63     InvalidateSize();
64     MainPageSizeChangedEventArgs^ args = ref new MainPageSizeChangedEventArgs();
65     args->ViewState = ApplicationView::Value;
66     MainPageResized(this, args);
67 
68 }
69 
InvalidateSize()70 void MainPage::InvalidateSize()
71 {
72     // Get the window width
73     double windowWidth = this->ActualWidth;
74 
75     if (windowWidth != 0.0)
76     {
77         // Get the width of the ListBox.
78         double listBoxWidth = Scenarios->ActualWidth;
79 
80         // Is the ListBox using any margins that we need to consider?
81         double listBoxMarginLeft = Scenarios->Margin.Left;
82         double listBoxMarginRight = Scenarios->Margin.Right;
83 
84         // Figure out how much room is left after considering the list box width
85         double availableWidth = windowWidth - listBoxWidth;
86 
87         // Is the top most child using margins?
88         double layoutRootMarginLeft = ContentRoot->Margin.Left;
89         double layoutRootMarginRight = ContentRoot->Margin.Right;
90 
91         // We have different widths to use depending on the view state
92         if (ApplicationView::Value != ApplicationViewState::Snapped)
93         {
94             // Make us as big as the the left over space, factoring in the ListBox width, the ListBox margins.
95             // and the LayoutRoot's margins
96             InputSection->Width = ((availableWidth) -
97                 (layoutRootMarginLeft + layoutRootMarginRight + listBoxMarginLeft + listBoxMarginRight));
98         }
99         else
100         {
101             // Make us as big as the left over space, factoring in just the LayoutRoot's margins.
102             if (autoSizeInputSectionWhenSnapped)
103             {
104                 InputSection->Width = (windowWidth - (layoutRootMarginLeft + layoutRootMarginRight));
105             }
106         }
107     }
108     InvalidateViewState();
109 }
110 
InvalidateViewState()111 void MainPage::InvalidateViewState()
112 {
113     // Are we going to snapped mode?
114     if (ApplicationView::Value == ApplicationViewState::Snapped)
115     {
116         Grid::SetRow(DescriptionText, 3);
117         Grid::SetColumn(DescriptionText, 0);
118 
119         Grid::SetRow(InputSection, 4);
120         Grid::SetColumn(InputSection, 0);
121 
122         Grid::SetRow(FooterPanel, 2);
123         Grid::SetColumn(FooterPanel, 0);
124     }
125     else
126     {
127         Grid::SetRow(DescriptionText, 1);
128         Grid::SetColumn(DescriptionText, 1);
129 
130         Grid::SetRow(InputSection, 2);
131         Grid::SetColumn(InputSection, 1);
132 
133         Grid::SetRow(FooterPanel, 1);
134         Grid::SetColumn(FooterPanel, 1);
135     }
136 
137     //  Since we don't load the scenario page in the traditional manner (we just pluck out the
138     // input and output sections from the page) we need to ensure that any VSM code used
139     // by the scenario's input and output sections is fired.
140     VisualStateManager::GoToState(InputSection, "Input" + LayoutAwarePage::DetermineVisualState(ApplicationView::Value), false);
141     VisualStateManager::GoToState(OutputSection, "Output" + LayoutAwarePage::DetermineVisualState(ApplicationView::Value), false);
142 }
143 
PopulateScenarios()144 void MainPage::PopulateScenarios()
145 {
146     ScenarioList = ref new Platform::Collections::Vector<Object^>();
147 
148     // Populate the ListBox with the list of scenarios as defined in Constants.cpp.
149     for (unsigned int i = 0; i < scenarios->Length; ++i)
150     {
151         Scenario s = scenarios[i];
152         ListBoxItem^ item = ref new ListBoxItem();
153         item->Name = s.ClassName;
154         item->Content = (i + 1).ToString() + ") " + s.Title;
155         ScenarioList->Append(item);
156     }
157 
158     // Bind the ListBox to the scenario list.
159     Scenarios->ItemsSource = ScenarioList;
160     Scenarios->ScrollIntoView(Scenarios->SelectedItem);
161 }
162 
163 /// <summary>
164 /// This method is responsible for loading the individual input and output sections for each scenario.  This
165 /// is based on navigating a hidden Frame to the ScenarioX.xaml page and then extracting out the input
166 /// and output sections into the respective UserControl on the main page.
167 /// </summary>
168 /// <param name="scenarioName"></param>
169 void MainPage::LoadScenario(String^ scenarioName)
170 {
171     autoSizeInputSectionWhenSnapped = true;
172 
173     // Load the ScenarioX.xaml file into the Frame.
174     TypeName scenarioType = {scenarioName, TypeKind::Custom};
175     HiddenFrame->Navigate(scenarioType, this);
176 
177     // Get the top element, the Page, so we can look up the elements
178     // that represent the input and output sections of the ScenarioX file.
179     Page^ hiddenPage = safe_cast<Page^>(HiddenFrame->Content);
180 
181     // Get each element.
182     UIElement^ input = safe_cast<UIElement^>(hiddenPage->FindName("Input"));
183     UIElement^ output = safe_cast<UIElement^>(hiddenPage->FindName("Output"));
184 
185     if (input == nullptr)
186     {
187         // Malformed input section.
188         NotifyUser("Cannot load scenario input section for " + scenarioName +
189             "  Make sure root of input section markup has x:Name of 'Input'", NotifyType::ErrorMessage);
190         return;
191     }
192 
193     if (output == nullptr)
194     {
195         // Malformed output section.
196         NotifyUser("Cannot load scenario output section for " + scenarioName +
197             "  Make sure root of output section markup has x:Name of 'Output'", NotifyType::ErrorMessage);
198         return;
199     }
200 
201     // Find the LayoutRoot which parents the input and output sections in the main page.
202     Panel^ panel = safe_cast<Panel^>(hiddenPage->FindName("LayoutRoot"));
203 
204     if (panel != nullptr)
205     {
206         unsigned int index = 0;
207         UIElementCollection^ collection = panel->Children;
208 
209         // Get rid of the content that is currently in the intput and output sections.
210         collection->IndexOf(input, &index);
211         collection->RemoveAt(index);
212 
213         collection->IndexOf(output, &index);
214         collection->RemoveAt(index);
215 
216         // Populate the input and output sections with the newly loaded content.
217         InputSection->Content = input;
218         OutputSection->Content = output;
219 
220         ScenarioLoaded(this, nullptr);
221     }
222     else
223     {
224         // Malformed Scenario file.
225         NotifyUser("Cannot load scenario: " + scenarioName + ".  Make sure root tag in the '" +
226             scenarioName + "' file has an x:Name of 'LayoutRoot'", NotifyType::ErrorMessage);
227     }
228 }
229 
230 void MainPage::Scenarios_SelectionChanged(Object^ sender, SelectionChangedEventArgs^ e)
231 {
232     if (Scenarios->SelectedItem != nullptr)
233     {
234         NotifyUser("", NotifyType::StatusMessage);
235 
236         LoadScenario((safe_cast<ListBoxItem^>(Scenarios->SelectedItem))->Name);
237         InvalidateSize();
238     }
239 }
240 
241 void MainPage::NotifyUser(String^ strMessage, NotifyType type)
242 {
243     switch (type)
244     {
245     case NotifyType::StatusMessage:
246         // Use the status message style.
247         StatusBlock->Style = safe_cast<Windows::UI::Xaml::Style^>(this->Resources->Lookup("StatusStyle"));
248         break;
249     case NotifyType::ErrorMessage:
250         // Use the error message style.
251         StatusBlock->Style = safe_cast<Windows::UI::Xaml::Style^>(this->Resources->Lookup("ErrorStyle"));
252         break;
253     default:
254         break;
255     }
256     StatusBlock->Text = strMessage;
257 
258     // Collapsed the StatusBlock if it has no text to conserve real estate.
259     if (StatusBlock->Text != "")
260     {
261         StatusBlock->Visibility = Windows::UI::Xaml::Visibility::Visible;
262     }
263     else
264     {
265         StatusBlock->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
266     }
267 }
268 
269 void MainPage::Footer_Click(Object^ sender, RoutedEventArgs^ e)
270 {
271     auto uri = ref new Uri((String^)((HyperlinkButton^)sender)->Tag);
272     Windows::System::Launcher::LaunchUriAsync(uri);
273 }
274 
275 
276 /// <summary>
277 /// Populates the page with content passed during navigation.  Any saved state is also
278 /// provided when recreating a page from a prior session.
279 /// </summary>
280 /// <param name="navigationParameter">The parameter value passed to
281 /// <see cref="Frame::Navigate(Type, Object)"/> when this page was initially requested.
282 /// </param>
283 /// <param name="pageState">A map of state preserved by this page during an earlier
284 /// session.  This will be null the first time a page is visited.</param>
285 void MainPage::LoadState(Object^ navigationParameter, IMap<String^, Object^>^ pageState)
286 {
287     (void) navigationParameter;    // Unused parameter
288 
289     PopulateScenarios();
290 
291     // Starting scenario is the first or based upon a previous state.
292     ListBoxItem^ startingScenario = nullptr;
293     int startingScenarioIndex = -1;
294 
295     if (pageState != nullptr && pageState->HasKey("SelectedScenarioIndex"))
296     {
297         startingScenarioIndex = safe_cast<int>(pageState->Lookup("SelectedScenarioIndex"));
298     }
299 
300     Scenarios->SelectedIndex = startingScenarioIndex != -1 ? startingScenarioIndex : 0;
301 
302     InvalidateViewState();
303 }
304 
305 /// <summary>
306 /// Preserves state associated with this page in case the application is suspended or the
307 /// page is discarded from the navigation cache.  Values must conform to the serialization
308 /// requirements of <see cref="SuspensionManager::SessionState"/>.
309 /// </summary>
310 /// <param name="pageState">An empty map to be populated with serializable state.</param>
311 void MainPage::SaveState(IMap<String^, Object^>^ pageState)
312 {
313     int selectedListBoxItemIndex = Scenarios->SelectedIndex;
314     pageState->Insert("SelectedScenarioIndex", selectedListBoxItemIndex);
315 }
316