In Xamarin, how to avoid memory leak when using Navigation.RemovePage() - xamarin.forms

In my Xamarin app, I have Five pages, Page 1, Page 2, Page 3, Page 4 and Page 5. When navigating from Page 5 to Page 3, I called Navigation.RemovePage() to remove Page 4 in NavigationStack. However, there is huge memory leak when calling RemovePage(). I want to know if there is any workaround to avoid memory leak when trying to remove the page between two pages in the NavigationStack? (Since Page 3 is not the Root Page, so I can't use PopToRootAsync())
Also, anyone can explains me why using PushModalAsync() will remove all pages in NavigationStack and only leaves the current added page and in both NavigationStack and ModalStack.
Thank you very much.

In Xamarin, how to avoid memory leak when using Navigation.RemovePage()
During testing, it will not leak memory when the RemovePage method is called.
private void Button_Clicked(object sender, EventArgs e)
{
Navigation.RemovePage( Navigation.NavigationStack.Where(a=> a is Page4).FirstOrDefault());
}
anyone can explains me why using PushModalAsync() will remove all pages in NavigationStack and only leaves the current added page and in both NavigationStack and ModalStack.
The matched with PushModalAsync navigation behavior in UWP platform is showing a ContentDialog. And it will not effect NavigationStack
The following is the test code.
private void PushClick(object sender, EventArgs e)
{
Navigation.PushModalAsync(new MainPage());
foreach (var item in Navigation.NavigationStack)
{
System.Diagnostics.Debug.WriteLine(item.GetType().Name);
}
}
For complete code sample please refer this link.

A simple test to check if your app leaks memory might be helpful. Enforce garbage collection after the operation you are investigating. Understanding how the .net garbage collector works might also be helpful link.
Look at the memory consumption before you remove the page and after. For test purposes force garbage collection right after the page is removed
private void Button_Clicked(object sender, EventArgs e)
{
Navigation.RemovePage( Navigation.NavigationStack.Where(a=> a is Page4).FirstOrDefault());
GC.Collect(2, GCCollectionMode.Forced);
}

Related

In Forms UWP, back navigation with content view in custom title view not working correct with custom renderer

Description
When using custom renderer for the content view. It throws "Element is already the child of another element" while converting the content of the content view to the content presenter using the content control.
Steps to Reproduce
Run the attached sample.
Navigate to the sub page and navigate back.
Content view gets hidden and page not navigated back properly.
Exception gets thrown in the on element changed method of custom renderer.
Expected Behavior
Page should be navigated back properly with the content view as like the second time.
Actual Behavior
In first time page is not navigated back properly and also content view gets disappear.
Screenshots
Actual Output
Expected Output
Workaround
Please check the below sample.
CustomControl.zip
Can anyone help me with this?
Element is already the child of another element"
The problem is your CustomView has been referenced by previous view, when you navigation back, the navigation create new ContentPage that want to use previous CustomView, but the previous CustomView has not be released. For solving this problem, you could set TitleViewProperty as null when page OnDisappearing.
protected override void OnDisappearing()
{
base.OnDisappearing();
SetValue(NavigationPage.TitleViewProperty, null);
}
Update
Please set TitleViewProperty in OnAppearing method like the following.
protected override void OnAppearing()
{
base.OnAppearing();
SetValue(NavigationPage.TitleViewProperty, new NavigationView());
}
protected override void OnDisappearing()
{
base.OnDisappearing();
SetValue(NavigationPage.TitleViewProperty, null);
}

Ext.net dynamic gridPanel reading from an httpHandler

I am adding a dynamic grid to a view port on click of a button the data in the store is from an ajax proxy , I am using the same code as in http://examples.ext.net/#/GridPanel/Saving_Variations/HttpHandler/
but the difference is I am adding it in behind code .
First problem is all the icon are not showing it is saying that it is cannot be found.
Second problem is that I am getting the headers and the buttons and they are functioning properly but there is no data displayed in the grid ...
Please help I have tried every thing I know here .
Firstly the icons may need to be registered in order for them to be rendered. Use the following code. This is especially true when loading icons dynamically.
protected void Page_Load(object sender, EventArgs e)
{
if(!X.IsAjaxRequest)
{
this.resourceManager.RegisterIcon(Icon.Lorry);
}
}
Secondly, if you are seeing blank rows in the grid it would suggest the data is being loaded but that you have a case mis-match between your ModelField and Column DataIndex value(s). DataIndex values are CASE SENSITIVE.
I hope this helps.
Thanks,
Gav

ASP.NET treeview performance issue with IE7,8

I am using treeview in my asp.net application which have 2000 nodes in it. The treeview takes 40 sec to load on IE7,8 while same page takes 1/10th time on Firefox and chrome. Is there any solution to this problem. Tried searching for this but found only unanswered questions. If this is a limitation of IE 7,8 then what is the reason for it. Is it because of the rendering engine. Is there any solution to the problem ? I mean i tried using the jquery treeview but again it hangs the IE and alert popups up for slow script.
Please help.
Have you tried this jQuery plugin? http://www.jstree.com/
It supports AJAX loading, which is great for a 2000 node tree.
When you open the rendered html generated from the tree view, you will find that the control generate a hell of html table, tr and td which I think is taking a very long time to be rendered on IE so I suggest that you create a new custom web control that inhertis from the treeview control and update the "Render Method" to write Div's instead of HTML and this will require a professional developer and HTML designer to do this.
I think you can after that share this new control with the community and we can enhance on it with you to get rid of this dummy asp.net gridview.
There must be something else going on. I did some performance testing on TreeView and was able to render a complex tree structure containing 5000 nodes in far less time then 40 seconds. A 2000 node complex tree rendered in about 3 seconds in IE8. If you can provide some more details about your tree maybe I can provide more assistance.
I've read that the amount of rendered HTML is one of the biggest factors when it comes to rendering time on a big tree. Even simple things such as reducing the length of a URL string by shortening a page name (if your nodes link directly to pages) or replacing CSS classes with more advanced style sheet usage techniques can make it considerably faster.
Below is my code for generating a random complex tree of _nodeCount size:
ASPX Page has a TreeView named tv:
<asp:TreeView ID="tv" runat="server"></asp:TreeView>
Code Behind looks like the following:
private Random _rand = new Random();
private int _nodeCount = 2000;
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
//create a big tree
var itemCount = 0;
while (itemCount < _nodeCount)
{
//create a parent item
var n = new TreeNode("Node " + itemCount.ToString(), itemCount.ToString());
itemCount++;
tv.Nodes.Add(n);
CreateSubItem(n, ref itemCount);
}
}
}
protected void CreateSubItem(TreeNode parent, ref int itemCount)
{
//chance that we won't create a sub item
if (_rand.Next(2) == 1 || itemCount > _nodeCount)
{
return;
}
var n = new TreeNode("Child Node " + itemCount.ToString(), itemCount.ToString());
itemCount++;
parent.ChildNodes.Add(n);
CreateSubItem(n, ref itemCount);
CreateSubItem(parent, ref itemCount);
}
Update 7/20
Perhaps you could take the logic in your javascript for setting icons and move it into .NET code, this should greatly reduce the page load time. This page, http://weblogs.asp.net/dannychen/archive/2006/01/25/436454.aspx, shows how to customize the rendering of a TreeNode; maybe it could be a good starting place for you.
It is always good to use AJAX in your application and load the treeview dynamically via AJAX. Here is a link...
http://www.codeproject.com/KB/ajax/selfloadelement.aspx
Setting the attribute HoverNodeStyle-CssClass="nh" makes the rendering of the TreeView slow in IE9. I removed the attribute and the performance restored.

Dropthings and loading user control content

I started looking at the dropthings portal and I don't understand how the content within the widget gets loaded. My understanding is that the header is in an Updatepanel and the body of the widget is in an UpdatePanel with a ASP Panel in it. When the page loads, the ASP Panels of all the widgets load first before loading the User controls within the panels.
Can someone explain how this happens and point me to the code where this is setup?
Any help is appreciated
I'm using version 2.7.5 (released Jan 11), so this might be a bit newer.
Each widget is a user control, and is hosted in a WidgetContainer.ascx. The WidgetContainer provides all the common functions like the title renaming, positioning, expand/collapse, editing, etc. The source file is in the root "dropthings" folder. Looking at the Init method, we can see where the UserControl instantiated & added to the page:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
var widget = LoadControl(this.WidgetInstance.Widget.Url); //Here's the magic
widget.ID = "Widget" + this.WidgetInstance.Id.ToString();
WidgetBodyPanel.Controls.Add(widget);
_WidgetRef = widget as IWidget;
if (_WidgetRef != null) _WidgetRef.Init(this);
}
So, first the WidgetContainer is added to the control tree for each Widget configured. Then as each container is initialized, it creates then adds the specific UserControl to the page. When
WidgetBodyPanel.Controls.Add(widget);
is called, it will initialize (OnInit) the specific widget. From there the contents of the widget are in it's own hands.

Is there a way to get images to display with ASP.NET and app_offline.htm?

When using the app_offline.htm feature of ASP.NET, it only allows html, but no images. Is there a way to get images to display without having to point them to a different url on another site?
Yes, it just can't come from the site that has the app_offline.htm file. The image would have to be hosted elsewhere.
Another solution is to embed the image inside the app_offline.htm page using a data URI. There is wide support for this these days - see the following for full details -
http://en.wikipedia.org/wiki/Data_URI_scheme
If you don't support browsers prior to IE 8, you can always embed the images using a data URI.
http://css-tricks.com/data-uris/
If you're willing to do a little more work you can easily create a custom page to take the application offline.
One possible solution:
Create DisplayOfflineMessage.aspx: Contains label to display your offline message from Application["OfflineMessage"].
ManageOfflineStatus.aspx: Contains an offline/online checkbox, textarea for offline message and an update button. The update button sets two application level variables, one for the message and a flag that states if the application is online. (This page should only be accessible to admins)
Then in Global.asax
public void Application_Start(object sender, EventArgs e)
{
Application["OfflineMessage"] = "This website is offline.";
Application["IsOffline"] = false;
}
public void Application_OnBeginRequest(object sender, EventArgs e)
{
bool offline = Convert.ToBoolean(Application["IsOffline"]);
if (offline)
{
// TODO: allow access to DisplayOfflineMessage.aspx and ManageOfflineStatus.aspx
// redirct requests to all other pages
Response.Redirect("~/DisplayOfflineMessage.aspx");
}
}
I have an idea.
You can create separate application, pointed to the same folder, without ASP.NET enabled. Then accessing to images by this application will not be affected by app_offline.htm file.
Or, point that application direсtly to folder with static content, there will not be any app_offline files.
But, of course, you need to assign separate dns name for this application, kind of static.somedomain.com.
You could just convert your images to base64 and then display them:
<html>
<body>
<h1>
Web under maintenance with image in base64
</h1>
<img src="data:image/png;base64,iVBORw0K...=">
</body>
</html>
I've created a Fiddle where you can see it in action

Resources