//********************************************************* // // Copyright (c) Microsoft. All rights reserved. // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT. // //********************************************************* using System; using Windows.UI.ViewManagement; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Markup; using Windows.UI.Xaml.Navigation; namespace SDKTemplate { /// <summary> /// An empty page that can be used on its own or navigated to within a Frame. /// </summary> public sealed partial class MainPage : SDKTemplate.Common.LayoutAwarePage { public event System.EventHandler ScenarioLoaded; public event EventHandler<MainPageSizeChangedEventArgs> MainPageResized; public bool AutoSizeInputSectionWhenSnapped = true; public Windows.ApplicationModel.Activation.LaunchActivatedEventArgs LaunchArgs { get { return ((App)App.Current).LaunchArgs; } } public static MainPage Current; private Frame HiddenFrame = null; public MainPage() { this.InitializeComponent(); // This is a static public property that will allow downstream pages to get // a handle to the MainPage instance in order to call methods that are in this class. Current = this; // This frame is hidden, meaning it is never shown. It is simply used to load // each scenario page and then pluck out the input and output sections and // place them into the UserControls on the main page. HiddenFrame = new Windows.UI.Xaml.Controls.Frame(); HiddenFrame.Visibility = Windows.UI.Xaml.Visibility.Collapsed; LayoutRoot.Children.Add(HiddenFrame); // Populate the sample title from the constant in the Constants.cs file. SetFeatureName(FEATURE_NAME); Scenarios.SelectionChanged += Scenarios_SelectionChanged; SizeChanged += MainPage_SizeChanged; Initialize(); } void MainPage_SizeChanged(object sender, SizeChangedEventArgs e) { InvalidateSize(); if (MainPageResized != null) { MainPageSizeChangedEventArgs args = new MainPageSizeChangedEventArgs(); args.ViewState = ApplicationView.Value; MainPageResized(this, args); } } /// <summary> /// Invoked when this page is about to be displayed in a Frame. /// </summary> /// <param name="e">Event data that describes how this page was reached. The Parameter /// property is typically used to configure the page.</param> protected override void OnNavigatedTo(NavigationEventArgs e) { PopulateScenarios(); InvalidateViewState(); } private void InvalidateSize() { // Get the window width double windowWidth = this.ActualWidth; if (windowWidth != 0.0) { // Get the width of the ListBox. double listBoxWidth = Scenarios.ActualWidth; // Is the ListBox using any margins that we need to consider? double listBoxMarginLeft = Scenarios.Margin.Left; double listBoxMarginRight = Scenarios.Margin.Right; // Figure out how much room is left after considering the list box width double availableWidth = windowWidth - listBoxWidth; // Is the top most child using margins? double layoutRootMarginLeft = ContentRoot.Margin.Left; double layoutRootMarginRight = ContentRoot.Margin.Right; // We have different widths to use depending on the view state if (ApplicationView.Value != ApplicationViewState.Snapped) { // Make us as big as the the left over space, factoring in the ListBox width, the ListBox margins. // and the LayoutRoot's margins InputSection.Width = availableWidth - (layoutRootMarginLeft + layoutRootMarginRight + listBoxMarginLeft + listBoxMarginRight); OutputSection.Width = windowWidth - (layoutRootMarginLeft + layoutRootMarginRight); } else { // Make us as big as the left over space, factoring in just the LayoutRoot's margins. if (AutoSizeInputSectionWhenSnapped) { InputSection.Width = windowWidth - (layoutRootMarginLeft + layoutRootMarginRight); OutputSection.Width = windowWidth - (layoutRootMarginLeft + layoutRootMarginRight); } } } InvalidateViewState(); } private void InvalidateViewState() { if (ApplicationView.Value == ApplicationViewState.Snapped) { Grid.SetRow(DescriptionText, 3); Grid.SetColumn(DescriptionText, 0); Grid.SetRow(InputSection, 4); Grid.SetColumn(InputSection, 0); Grid.SetRow(FooterPanel, 2); Grid.SetColumn(FooterPanel, 0); } else { Grid.SetRow(DescriptionText, 1); Grid.SetColumn(DescriptionText, 1); Grid.SetRow(InputSection, 2); Grid.SetColumn(InputSection, 1); Grid.SetRow(FooterPanel, 1); Grid.SetColumn(FooterPanel, 1); } // Since we don't load the scenario page in the traditional manner (we just pluck out the // input and output sections from the page) we need to ensure that any VSM code used // by the scenario's input and output sections is fired. VisualStateManager.GoToState((Control)InputSection, "Input" + ApplicationView.Value.ToString(), false); VisualStateManager.GoToState((Control)OutputSection, "Output" + ApplicationView.Value.ToString(), false); } private void PopulateScenarios() { System.Collections.ObjectModel.ObservableCollection<object> ScenarioList = new System.Collections.ObjectModel.ObservableCollection<object>(); int i = 0; // Populate the ListBox with the list of scenarios as defined in Constants.cs. foreach (Scenario s in scenarios) { ListBoxItem item = new ListBoxItem(); s.Title = (++i).ToString() + ") " + s.Title; item.Content = s; item.Name = s.ClassType.FullName; ScenarioList.Add(item); } // Bind the ListBox to the scenario list. Scenarios.ItemsSource = ScenarioList; // Starting scenario is the first or based upon a previous selection. int startingScenarioIndex = -1; if (SuspensionManager.SessionState.ContainsKey("SelectedScenarioIndex")) { int selectedScenarioIndex = Convert.ToInt32(SuspensionManager.SessionState["SelectedScenarioIndex"]); startingScenarioIndex = selectedScenarioIndex; } Scenarios.SelectedIndex = startingScenarioIndex != -1 ? startingScenarioIndex : 0; } /// <summary> /// This method is responsible for loading the individual input and output sections for each scenario. This /// is based on navigating a hidden Frame to the ScenarioX.xaml page and then extracting out the input /// and output sections into the respective UserControl on the main page. /// </summary> /// <param name="scenarioName"></param> public void LoadScenario(Type scenarioClass) { AutoSizeInputSectionWhenSnapped = true; // Load the ScenarioX.xaml file into the Frame. HiddenFrame.Navigate(scenarioClass, this); // Get the top element, the Page, so we can look up the elements // that represent the input and output sections of the ScenarioX file. Page hiddenPage = HiddenFrame.Content as Page; // Get each element. UIElement input = hiddenPage.FindName("Input") as UIElement; UIElement output = hiddenPage.FindName("Output") as UIElement; if (input == null) { // Malformed input section. NotifyUser(String.Format( "Cannot load scenario input section for {0}. Make sure root of input section markup has x:Name of 'Input'", scenarioClass.Name), NotifyType.ErrorMessage); return; } if (output == null) { // Malformed output section. NotifyUser(String.Format( "Cannot load scenario output section for {0}. Make sure root of output section markup has x:Name of 'Output'", scenarioClass.Name), NotifyType.ErrorMessage); return; } // Find the LayoutRoot which parents the input and output sections in the main page. Panel panel = hiddenPage.FindName("LayoutRoot") as Panel; if (panel != null) { // Get rid of the content that is currently in the intput and output sections. panel.Children.Remove(input); panel.Children.Remove(output); // Populate the input and output sections with the newly loaded content. InputSection.Content = input; OutputSection.Content = output; } else { // Malformed Scenario file. NotifyUser(String.Format( "Cannot load scenario: '{0}'. Make sure root tag in the '{0}' file has an x:Name of 'LayoutRoot'", scenarioClass.Name), NotifyType.ErrorMessage); } } void Scenarios_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (Scenarios.SelectedItem != null) { NotifyUser("", NotifyType.StatusMessage); ListBoxItem selectedListBoxItem = Scenarios.SelectedItem as ListBoxItem; SuspensionManager.SessionState["SelectedScenarioIndex"] = Scenarios.SelectedIndex; Scenario scenario = selectedListBoxItem.Content as Scenario; LoadScenario(scenario.ClassType); InvalidateSize(); // Fire the ScenarioLoaded event since we know that everything is loaded now. if (ScenarioLoaded != null) { ScenarioLoaded(this, new EventArgs()); } ValidateFile(scenario.ClassType); } } public void NotifyUser(string strMessage, NotifyType type) { switch (type) { // Use the status message style. case NotifyType.StatusMessage: StatusBlock.Style = Resources["StatusStyle"] as Style; break; // Use the error message style. case NotifyType.ErrorMessage: StatusBlock.Style = Resources["ErrorStyle"] as Style; break; } StatusBlock.Text = strMessage; // Collapse the StatusBlock if it has no text to conserve real estate. if (StatusBlock.Text != String.Empty) { StatusBlock.Visibility = Windows.UI.Xaml.Visibility.Visible; } else { StatusBlock.Visibility = Windows.UI.Xaml.Visibility.Collapsed; } } async void Footer_Click(object sender, RoutedEventArgs e) { await Windows.System.Launcher.LaunchUriAsync(new Uri(((HyperlinkButton)sender).Tag.ToString())); } private void SetFeatureName(string str) { FeatureName.Text = str; } } public class MainPageSizeChangedEventArgs : EventArgs { private ApplicationViewState viewState; public ApplicationViewState ViewState { get { return viewState; } set { viewState = value; } } } public enum NotifyType { StatusMessage, ErrorMessage, }; }