public void ReduceMemoryUsage() { // If the app has caches or other memory it can free, it should do so now. // << App can release memory here >> // Additionally, if the application is currently // in background mode and still has a view with content // then the view can be released to save memory and // can be recreated again later when leaving the background. if (Window.Current.Content != null) { // Some apps may wish to use this helper to explicitly disconnect // child references. VisualTreeHelper.DisconnectChildrenRecursive(Window.Current.Content); NavigationService.Instance = null; // Clear the view content. Note that views should rely on // events like Page.Unloaded to further release resources. // Release event handlers in views since references can // prevent objects from being collected. Window.Current.Content = null; } // Run the GC to collect released resources. GC.Collect(); }
/// <summary> /// Reduces application memory usage. /// </summary> /// <remarks> /// When the app enters the background, receives a memory limit changing /// event, or receives a memory usage increased event, it can /// can optionally unload cached data or even its view content in /// order to reduce memory usage and the chance of being suspended. /// This must be called from multiple event handlers because an application may already /// be in a high memory usage state when entering the background, or it /// may be in a low memory usage state with no need to unload resources yet /// and only enter a higher state later. /// </remarks> private async Task ReduceMemoryUsageAsync() { try { // Run on UI thread await DispatcherHelper.ExecuteOnUIThreadAsync(() => { // Additionally, if the application is currently // in background mode and still has a view with content // then the view can be released to save memory and // can be recreated again later when leaving the background. if (!DeviceHelper.IsBackground || Window.Current == null || Window.Current.Content == null) { return; } // Get the main shell and only continue if it exists var shell = Window.Current.Content as MainShell; if (shell == null) { return; } shell.RootFrame.Navigate(typeof(BlankPage)); shell.Dispose(); // Clear the page cache var cacheSize = shell.RootFrame.CacheSize; shell.RootFrame.CacheSize = 0; shell.RootFrame.CacheSize = cacheSize; // Clear backstack shell.RootFrame.BackStack.Clear(); // Clear refrences VisualTreeHelper.DisconnectChildrenRecursive(shell.RootFrame); VisualTreeHelper.DisconnectChildrenRecursive(shell); shell.RootFrame = null; // Clear the view content. Note that views should rely on // events like Page.Unloaded to further release resources. // Release event handlers in views since references can // prevent objects from being collected. Window.Current.Content = null; GC.Collect(); }); } catch { // This will crash if no main view is active } // Run the GC to collect released resources on background thread. GC.Collect(); }
protected override void OnApplyTemplate() { if (Windows.ApplicationModel.DesignMode.DesignModeEnabled) { return; } VisualStateManager.GoToState(this, "ResetState", false); MasterPresenter = (ContentPresenter)GetTemplateChild("MasterFrame"); DetailPresenter = (Grid)GetTemplateChild("DetailPresenter"); AdaptivePanel = (MasterDetailPanel)GetTemplateChild("AdaptivePanel"); AdaptivePanel.ViewStateChanged += OnViewStateChanged; MasterPresenter.RegisterPropertyChangedCallback(VisibilityProperty, OnVisibilityChanged); var detailVisual = ElementCompositionPreview.GetElementVisual(DetailPresenter); detailVisual.Clip = Window.Current.Compositor.CreateInsetClip(); if (DetailFrame != null) { var parent = VisualTreeHelper.GetParent(DetailFrame) as UIElement; if (parent != null && parent != DetailPresenter) { VisualTreeHelper.DisconnectChildrenRecursive(parent); } //Grid.SetRow(DetailFrame, 1); try { DetailFrame.Navigated += OnNavigated; DetailPresenter.Children.Add(DetailFrame); if (DetailFrame.CurrentSourcePageType == null) { DetailFrame.Navigate(BlankPageType); } else { DetailFrame.BackStack.Insert(0, new PageStackEntry(BlankPageType, null, null)); } } catch { } } if (ActualWidth > 0) { UpdateVisualState(); if (CurrentState != MasterDetailState.Minimal && ViewStateChanged != null) { ViewStateChanged(this, EventArgs.Empty); } } }
void RenderCurrentPointer() { SolidColorBrush strokeBrush = new SolidColorBrush(UseSystemAccentColorForCurrentPointers ? (Color)Resources["SystemAccentColor"] : Colors.Red); try { PlotArea.Children.Remove(PlotArea.Children.OfType <Line>().FirstOrDefault(p => p.Name == "CurrentDataPointer")); PlotArea.Children.Remove(PlotArea.Children.OfType <Line>().FirstOrDefault(p => p.Name == "CurrentDataPointerY")); } catch (InvalidOperationException) { } if (CurrentData != null) { var DesiredKey = Points.Keys.OrderBy(p => Math.Abs(p - (Double)CurrentData)).First(); var xStep = PlotArea.Width / (MathUtils.Limit(Points.Keys.Last() - Points.Keys.First(), 5, Points.Keys.Last() - Points.Keys.First())); var yStep = PlotArea.Height / (MathUtils.Limit(Points.Values.Max() - Points.Values.Min(), 5, Points.Values.Max() - Points.Values.Min())); PlotArea.Children.Add(new Line { Name = "CurrentDataPointer", X1 = (DesiredKey - Points.Keys.First()) * xStep, Y1 = 0, X2 = (DesiredKey - Points.Keys.First()) * xStep, Y2 = PlotArea.Height, Stroke = strokeBrush, StrokeThickness = 2 }); VisualTreeHelper.DisconnectChildrenRecursive(CurrentDataPointerLabelSpace); CurrentDataPointerLabelSpace.Children.Add(new TextBlock { Text = XMarkerConverter != null ? XMarkerConverter(DesiredKey) : DesiredKey.ToString(), RenderTransform = new TranslateTransform { X = (DesiredKey - Points.Keys.First()) * xStep } }); PlotArea.Children.Add(new Line { Name = "CurrentDataPointerY", X1 = 0, Y1 = PlotArea.Height - (Points[DesiredKey] - Points.Values.Min()) * yStep, X2 = PlotArea.Width, Y2 = PlotArea.Height - (Points[DesiredKey] - Points.Values.Min()) * yStep, Stroke = strokeBrush, StrokeThickness = 1 }); VisualTreeHelper.DisconnectChildrenRecursive(CurrentDataPointerLabelSpaceY); CurrentDataPointerLabelSpaceY.Children.Add(new TextBlock { Text = YMarkerConverter != null ? YMarkerConverter(Points[DesiredKey]) : Points[DesiredKey].ToString(), RenderTransform = new TranslateTransform { Y = PlotArea.Height - (Points[DesiredKey] - Points.Values.Min()) * yStep } }); } }
private void EvaluateCases() { if (CurrentCase != null && CurrentCase.Value != null && CurrentCase.Value.Equals(Value)) { // If the current case we're on already matches our current value, // then we don't have any work to do. return; } Case xdefault = null; Case newcase = null; foreach (var xcase in SwitchCases) { if (xcase.IsDefault) { // If there are multiple default cases provided, this will override and just grab the last one, the developer will have to fix this in their XAML. We call this out in the case comments. xdefault = xcase; continue; } if (CompareValues(Value, xcase.Value)) { newcase = xcase; break; } } if (newcase == null && xdefault != null) { // Inject default if we found one. newcase = xdefault; } // Only bother changing things around if we have a new case. if (newcase != CurrentCase) { // Disconnect old content from visual tree. if (CurrentCase != null && CurrentCase.Content != null && IsVisualTreeDisconnectedOnChange) { // TODO: If we disconnect here, we need to recreate later??? Need to Test... VisualTreeHelper.DisconnectChildrenRecursive(CurrentCase.Content); } // Hookup new content. Content = newcase.Content; CurrentCase = newcase; } }
/// <summary> /// Reduces application memory usage. /// </summary> /// <remarks> /// When the app enters the background, receives a memory limit changing /// event, or receives a memory usage increased event, it can /// can optionally unload cached data or even its view content in /// order to reduce memory usage and the chance of being suspended. /// This must be called from multiple event handlers because an application may already /// be in a high memory usage state when entering the background, or it /// may be in a low memory usage state with no need to unload resources yet /// and only enter a higher state later. /// </remarks> private void ReduceMemoryUsage() { var memUsage = MemoryManager.AppMemoryUsage; var removeUi = false; // If the app has caches or other memory it can free, it should do so now. // << App can release memory here >> // Additionally, if the application is currently // in background mode and still has a view with content // then the view can be released to save memory and // can be recreated again later when leaving the background. if (IsBackground && Window.Current != null && Window.Current.Content != null) { VisualTreeHelper.DisconnectChildrenRecursive(Window.Current.Content); // Clear the view content. Note that views should rely on // events like Page.Unloaded to further release resources. // Release event handlers in views since references can // prevent objects from being collected. Window.Current.Content = null; removeUi = true; } var shell = Window.Current?.Content as MainShell; shell?.RootFrame.Navigate(typeof(BlankPage)); // Clear the page cache if (shell?.RootFrame != null) { var cacheSize = shell.RootFrame.CacheSize; shell.RootFrame.CacheSize = 0; shell.RootFrame.CacheSize = cacheSize; } // Run the GC to collect released resources. GC.Collect(); var diffMemUsage = (memUsage - MemoryManager.AppMemoryUsage); TelemetryService.Current.TrackEvent("Memory Collection Completed", new Dictionary <string, string>() { { "cleaned_memory", diffMemUsage + "kb" }, { "is_background", IsBackground.ToString() }, { "remove_ui", removeUi.ToString() }, }); }
private void Page_Unloaded(object sender, RoutedEventArgs e) { try { Output.Items.Clear(); } catch { } gRID.Children.Clear(); GetHistory.limit = 50; GetHistory.skipInt = 0; GetHistory.firstrun = false; GetHistory.FirstId = null; VisualTreeHelper.DisconnectChildrenRecursive(this); }
protected override void OnApplyTemplate() { if (Windows.ApplicationModel.DesignMode.DesignModeEnabled) { return; } VisualStateManager.GoToState(this, "ResetState", false); MasterPresenter = (ContentPresenter)GetTemplateChild("MasterFrame"); DetailPresenter = (Grid)GetTemplateChild("DetailPresenter"); AdaptiveStates = (VisualStateGroup)GetTemplateChild("AdaptiveStates"); AdaptiveStates.CurrentStateChanged += OnCurrentStateChanged; MasterPresenter.RegisterPropertyChangedCallback(VisibilityProperty, OnVisibilityChanged); if (DetailFrame != null) { var parent = VisualTreeHelper.GetParent(DetailFrame) as UIElement; if (parent != null && parent != DetailPresenter) { VisualTreeHelper.DisconnectChildrenRecursive(parent); } DetailFrame.Navigated += OnNavigated; DetailPresenter.Children.Add(DetailFrame); if (DetailFrame.CurrentSourcePageType == null) { DetailFrame.Navigate(BlankPageType); } else { DetailFrame.BackStack.Insert(0, new PageStackEntry(BlankPageType, null, null)); } } if (ActualWidth > 0) { UpdateVisualState(); if (CurrentState != MasterDetailState.Narrow && ViewStateChanged != null) { ViewStateChanged(this, EventArgs.Empty); } } }
private async Task ReduceMemoryUsageAsync() { try { // Run on UI thread await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { // Additionally, if the application is currently // in background mode and still has a view with content // then the view can be released to save memory and // can be recreated again later when leaving the background. if (Window.Current == null || Window.Current.Content == null) { return; } // Delete all view models (App.Current.Resources["ViewModelLocator"] as ViewModelLocator)?.CleanViewModels(); // If desktop shell if (Window.Current.Content is DesktopShell desktopShell) { // Dispose the shell desktopShell.Dispose(); // Clear the page cache var cacheSize = desktopShell.RootFrame.CacheSize; desktopShell.RootFrame.CacheSize = 0; desktopShell.RootFrame.CacheSize = cacheSize; // Clear back-stack desktopShell.RootFrame.BackStack.Clear(); // Clear references VisualTreeHelper.DisconnectChildrenRecursive(desktopShell.RootFrame); VisualTreeHelper.DisconnectChildrenRecursive(desktopShell); } // If xbox shell if (Window.Current.Content is XboxShell xboxShell) { // Dispose the shell xboxShell.Dispose(); // Clear the page cache var cacheSize = xboxShell.RootFrame.CacheSize; xboxShell.RootFrame.CacheSize = 0; xboxShell.RootFrame.CacheSize = cacheSize; // Clear back-stack xboxShell.RootFrame.BackStack.Clear(); // Clear references VisualTreeHelper.DisconnectChildrenRecursive(xboxShell.RootFrame); VisualTreeHelper.DisconnectChildrenRecursive(xboxShell); } // Clear the view content. Note that views should rely on // events like Page.Unloaded to further release resources. // Release event handlers in views since references can // prevent objects from being collected. Window.Current.Content = null; // Allow us to init the window again _isInit = false; GC.Collect(); }); } catch { // This will crash if no main view is active } // Run the GC to collect released resources on background thread. GC.Collect(); }
public void ReRender(Size newSize) { if (Visibility == Visibility.Visible && ReRenderEnabled) { Debug.WriteLine("ReRendering"); PlotArea.Width = 3 * newSize.Width / 4; PlotArea.Height = 3 * newSize.Height / 4; if (Points.Count > 0) { VisualTreeHelper.DisconnectChildrenRecursive(PlotArea); VisualTreeHelper.DisconnectChildrenRecursive(XAxisLabels); VisualTreeHelper.DisconnectChildrenRecursive(YAxisLabels); var xStep = PlotArea.Width / (MathUtils.Limit(Points.Keys.Last() - Points.Keys.First(), 5, Points.Keys.Last() - Points.Keys.First())); var yStep = PlotArea.Height / (MathUtils.Limit(Points.Values.Max() - Points.Values.Min(), 5, Points.Values.Max() - Points.Values.Min())); for (Double i = Points.Keys.First(); i < Points.Keys.First() + 5 || i <= Points.Keys.Last(); i += (Points.Keys.Last() - Points.Keys.First() < 5) ? 1 : MathUtils.NearestToMultipleOf((Points.Keys.Last() - Points.Keys.First()) / 5, 5)) { PlotArea.Children.Add(new Line { X1 = (i - Points.Keys.First()) * xStep, Y1 = 0, X2 = (i - Points.Keys.First()) * xStep, Y2 = PlotArea.Height, Stroke = new SolidColorBrush(Colors.LightGray), StrokeThickness = 0.75 }); if (ShowXLabels) { XAxisLabels.Children.Add(new TextBlock { Text = XMarkerConverter != null ? XMarkerConverter(i) : i.ToString(), Margin = new Thickness((i - Points.Keys.First()) * xStep, 0, 0, 0) }); } } for (Double i = Points.Values.Min(); i < Points.Values.Min() + 5 || i <= Points.Values.Max(); i += (Points.Values.Max() - Points.Values.Min() < 5) ? 1 : MathUtils.NearestToMultipleOf((Points.Values.Max() - Points.Values.Min()) / 5, 5)) { PlotArea.Children.Add(new Line { X1 = 0, Y1 = PlotArea.Height - (i - Points.Values.Min()) * yStep, X2 = PlotArea.Width, Y2 = PlotArea.Height - (i - Points.Values.Min()) * yStep, Stroke = new SolidColorBrush(Colors.LightGray), StrokeThickness = 0.75 }); if (ShowYLabels) { YAxisLabels.Children.Add(new TextBlock { Text = YMarkerConverter != null ? YMarkerConverter(i) : i.ToString(), VerticalAlignment = VerticalAlignment.Bottom, RenderTransform = new TranslateTransform { Y = -(i - Points.Values.Min()) * yStep } }); } } var pointsEnumerator = Points.GetEnumerator(); pointsEnumerator.MoveNext(); KeyValuePair <Int32, Double> nextPair, currentPair = pointsEnumerator.Current; while (pointsEnumerator.MoveNext()) { nextPair = pointsEnumerator.Current; PlotArea.Children.Add(new Line { X1 = (currentPair.Key - Points.Keys.First()) * xStep, Y1 = PlotArea.Height - (currentPair.Value - Points.Values.Min()) * yStep, X2 = (nextPair.Key - Points.Keys.First()) * xStep, Y2 = PlotArea.Height - (nextPair.Value - Points.Values.Min()) * yStep, Stroke = new SolidColorBrush(Colors.White), StrokeThickness = 3 }); currentPair = nextPair; } } } }