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.
Related
I don't have so much experience using AJAX in a MVC application, in fact is my first facing. Please check the below image and note the rectangles.
The image is just an example that I took from internet.
The biggest rectangle is a partial view in my application and I have to render it when the user press Continue or Continuar button. The application should replace the current view for another without refresh the page.
This is the code which I'm testing, note first that I'm passing the first element of a list, but when the user press the button, render the view with the next element index = 2.
public ActionResult DoTest()
{
if (!Request.IsAjaxRequest())
{ }
List<Worksheet> worksheets = new List<Worksheet>()
{
new Worksheet("Hoja 1", ...),
new Worksheet("Hoja 2", ...)
};
return View(worksheets[0]);
}
Can orient me a little bit to know how to implement this feature? I just know that I need to use Ajax.
Have a look through the tutorials and examples here. There's plenty of other material around on the web with information on this subject.
There are many different ways you can achieve this. One way would be to write a custom paging Helper (HtmlHelper) that accepts new content upon the post event. You can view all about Helpers here : Custom HTML Helpers
Another way could be to use partial page rendering to achieve the partial page update upon post event.
If I was you I would combine a partial view with a jquery function to update the content. You can view some help on that here: Change dive content with Jquery
I am trying to download information from a website and I have hit (yet another) brick wall in a long and tiresome journey to get something productive developed.
I have a program which uses WebBrowser to login to a site - with a valid username and password - therby allowing me to set up a legitimate connection to it and retrieve information (my own) from it.
From the initial page presented to me after login, I can use WebBrowser.Document.GetElementsByTagName("A") and WebBrowser.Document.GetElementById("Some Id") etc. to work my way around the website, and processing all the DocumentCompleted events returned until ... I arrive at a page which appears to have a TabControl embedded in it.
I need to be able to choose the middle Tab of this control, and retrieve the information it holds. When I access this information 'normally' (i.e. from IE and not from my WebBrowser program) I can click each of the three tabs and information duly appears - so its there, tantalisingly so ... but can I manupulate these Tabs from my program? I feel it should be possible, but I can't see how I can do it.
The problem manifests itself because when I am processing the page which has the Tab in it my code looks like this:
static void wb_TabPage(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser wb = (WebBrowser)sender;
HtmlElement element;
element = wb.Document.GetElementById("Bills"); // Find the "Bills" tab
element.InvokeMember("Click"); // Click the "Bills" tab
// Unhook THIS routine from DocumentCompleted delivery
wb.DocumentCompleted -= new WebBrowserDocumentCompletedEventHandler(wb_TabPage);
// Hook up this routine - for the next 'Document Completed' delivery - which never arrives!
wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(wb_Bills);
return;
}
And that's the problem - no more Documents are ever 'Completed' for me to process, even after the InvokeMember("Click"). It seems for all the world that the Tabs are being updated inplace, and no amount of Refresh(ing) or Navigating or Event Handling will allow me to get to a place or in a position where I can get the data from them
Does anybody have any idea how I can do this? Does anybody know how to manipulate Tabs from WebBrowser? Thanks in advance if you do ...
Try using the findcontrol function on your page. You will likely need to drill into the tab control itself to find the tab page and the controls contained in it.
I need to have a grid on one of my webpages that will be used to enter budget information. I was planning on using a gridview, but I am open to other ideas if something else will fit my needs better. I need the following functionality in my grid:
All cells are in edit mode as soon as the page loads
Need a footer row at the bottom to
calculate totals for particular columns
I looked around for this functionality in the gridview for a bit but didn't have any luck. Any links or suggestions on how to do the two items above in a gridview would be greatly appreciated.
NOTE: I'm using Visual Studio 2008
IMO you are going to be much better off coding this yourself using a ListView. You can look into the DataBound() and ItemDataBound() events. The GridView does not come with the functionality built in.
OTOH, Matt Dotson has a blog post describing how to build a GridView with all rows in edit mode.
Totals in the footer can be applied using a combination of javascript executed on each data change and form load AND dynamically adding textboxes or labels to the footer via the GridView's RowDataBound event. For example,
// Create textboxes in footer to hold hours totals
if (e.Row.RowType == DataControlRowType.Footer)
{
e.Row.CssClass = "wgv-ft";
for (int i = 0; i < NumHoursTextBoxes; ++i)
{
var tb = new TextBox();
tb.ID = String.Format("Hours{0}TotalTextBox", i);
tb.CssClass = "total";
tb.Enabled = false;
e.Row.Cells[FirstHoursTextBoxIndex + i].Controls.Add(tb);
}
}
Rather than using the built-in edit functionality (EditItemTemplates) which the GridView offers, you might want to just use the ItemTemplates and always show an editable textboxes or other controls. I've used this technique. You can still take advantage of validators and the core ASP.NET control set, but you do have to write quite a bit of javascript to manage updates to the totals.
I hope this helps. Best of luck.
I'm developing a grid with excel-like functionality using the telerik controls. For example users can click on a cell and the cell turns into an input control for editing. Users can tab to move onto the next cell or use arrow keys for up/down to get the cell above or below. I've found the standard telerik grid is good but I've had to extend it with custom javascript to achieve what I need.
My problem is performance in the IE browser. While Firefox, Chrome, Safari are all fine, IE is a real pain. IE8 is considerably better than IE7 however moving around with the cursor keys is a bit unnatural, and nothing like as smooth as Chrome or FF.
I can't really post sample code due to the complexity of what the grid is doing, but generally I'm displaying the standard telerik grid and using the telerik javascript API to fill and bind in the browser. When a cell is clicked a javascript function moves a previously hidden input control into the cell from a hidden collection and gives it focus. When you tab away the cell value is cleared and the server is updated using ajax pagemethods and the next cell is selected in a similar manner.
The grid has approx 40 columns and 20 rows, i.e. 800 extra controls are hidden on the page and only activated by clicking a cell or through navigating with the keyboard. I originally had just one hidden control for each column but moving up and down with the cursor keys became problematic in IE.
Any advice for things to check that might speed up IE8 would be greatly appreciated.
//selects a cell and sets the value
this.select = function(value) {
this.moveFromTo(this._hiddenCell, this._gridCell);
this._bIsSelected = true;
this.set_inputValue(value);
this._focus();
}
//clears inner content for a cell
this.removeChildrenFromNode = function(node) {
if (node == undefined || node == null) {
return;
}
var len = node.childNodes.length;
while (node.hasChildNodes()) {
node.removeChild(node.firstChild);
}
}
//move back or forwards between hidden or active cell
this.moveFromTo = function(from, to) {
var currChild = null;
this.removeChildrenFromNode(to);
var i = 0;
if (from.childNodes != null) {
while (i < from.childNodes.length) {
currChild = from.childNodes[i];
if (to != null) to.appendChild(currChild);
i += 1;
}
}
this.removeChildrenFromNode(from);
}
Load up your page in IE8, open the developer toolbar F12 and turn on the profiling:
Profiler (tab) > Start Profiling
Use your grid for a bit as normal, and let IE profile your code.
When done, click Stop Profiling, and verify which function calls are chewing up the memory or taking the most time.
They may be ones that are beyond your control (e.g. in Telerik's code) but if anything you've added is the bottleneck post the function(s) back here on SO to ask for advise on how to optimize.
It sounds as though most if not all of your controls related to the grid are created from within JavaScript?
If so there are a couple of things to keep in mind:
IE hates string concatenation: there are numerous posts about it's poor performance
Ensure your clearing your events when switching controls and not just overwriting them
memory leaks are not your friend
IE hates adding controls as much as you do - so reuse them when possible
IE is faster if the controls are created via HTML (why oh why?)
IE hates it when you add lots of dynamic images and CSS with on-the-fly HTML controls
IE prefers innerHTML to addChild() (seems counter intuitive to string issue above)
etc
etc
There's many more, but with IE you also have to implement almost every single JavaScript performance suggestion you can find:
short variable names
ensure variables are properly scoped (otherwise the runtime will jump up scopes until nothing is left to search)
iterators from frameworks like prototype and jQuery are often slower than traditional for and while loops (VERY VERY sad but quite true)
etc
etc
When a cell is clicked a javascript
function moves a previously hidden
input control into the cell from a
hidden collection and gives it focus.
You have to explain the quote above in more detail. How exactly do you move the previously hidden control into the cell? Check the site below for a benchmark that uses different methods to generate a dynamic table. Moving the control using the W3C DOM methods or table methods could slow down IE while working fine in other browsers.
http://www.quirksmode.org/dom/innerhtml.html
Edit: Try this to check if it's faster(not as a final solution):
this.moveFromTo = function(from, to) {
to.innerHTML = from.innerHTML; }
Here are some useful links
Understanding and Solving Internet Explorer Leak Patterns
IE Sieve, Memory Leak detector for Internet Explorer
JavaScript Profiling
Try Google Frame. It pushes the performance on IE8 ;)
Test you code with jslint.com
Is there an accepted way to "move" a control.
My client wants to place a certain chunk of markup (representing some visual element) in one of several different places on the page. The locations are different to the point that I can't effect the change on CSS along (by floating it or something).
I considered just putting the control in multiple spots with Visible set to "false," then displaying the one in the place they wanted for that particular page.
However, the code for this control is not trivial -- there's a couple template sections, for instance. Having to dupe this in multiple places would get unwieldy. Also, I don't want to have to work with this control strictly from the code-behind for the same reason.
So, I'd like to put it in one place on the Web form, the move it around based on where I want it. Could I put Placeholders in different spots, have the control in one spot, then remove and add it to the right spot? I suspect this would work.
Does someone have a better idea? Is there a best practice for this?
I'd recommend using a placeholder control, moving your markup into a separate user control, then loading this at runtime and adding it to the relevant placeholder.
Eg.
// Load a user control
MyControl userCtrl = (MyControl) LoadControl("~/Controls/MyControl.ascx");
// Or create an instance of your control
SubclassedControl subclassedCtrl = new SubclassedControl();
// Do stuff with controls here
userCtrl.LoadData();
subclassedCtrl.Text = "Hello World";
// Check which placeholder to add controls to
PlaceHolder placeHolder = (foo=="bar") ? placeHolder1 : placeHolder2;
// Add the controls
placeHolder.Controls.Add(userCtrl);
placeHolder.Controls.Add(subclassedCtrl);
This will avoid cluttering up your page with unnecessary markup, and loading it at runtime will also avoid unnecessary confusion later, when another developer looks at the code and can't immediately see why a control is in one place in the markup, but renders on a completely different part of the page.
An alternative (and one I've seen done many times before) is through javascript and the DOM. Render your control inside a hidden div tag. So you would render your content here:
<div id='rendercontent' style='display:none'>
.. control here ..
</div>
Then, lets say you wanted to move it all here (the span tag is inside because that's what we're going to replace):
<div id='newlocation1'><span></span></div>
You would define the following javascript:
<script language="JavaScript">
function replaceNode(newElementID, targetElementID)
{
var targetElement=document.getElementById(targetElementID);
var newElement=document.getElementById(newElementID);
targetElement.replaceChild(newElement, targetElement.firstChild);
}
</script>
And when you want to move the content to the new location, call:
<script language="JavaScript">
replaceNode('rendercontent','newlocation1');
</script>
Do Web Parts do what you want to do?
Or, you can change the parent programmatically of your controls to move them into a separate area.
You can override the Render method and place the controls wherever you want in the html.
You only need to add controls to the Controls collection that must interact on the server. The rest of your HTML can just be written to the response stream. If you override Render you can create the html anyway you see fit, placing the controls in any order.
Below is an example of how to write out your html.
protected override void Render(HtmlTextWriter writer)
{
AddAttributesToRender(writer);
writer.RenderBeginTag(TagKey);
writer.RenderBeginTag(HtmlTextWriterTag.Div);
_control.RenderControl(writer);
writer.RenderEndTag();
writer.RenderEndTag();
}
You could always put panels in the pre-defined locations and add the control to the specific panel at runtime.. Here's an example adding a label (the label could be replaced with any control).
Dim lblDisplay As Label = New Label()
lblDisplay.ID = "myLabel"
lblDisplay.Text = "Some Text"
pnlDisplay.Controls.Add(lblDisplay)
As far as...
"Also, I don't want to have to work
with this control strictly from the
code-behind for the same reason."
I think you're going to have to do most of your work in the code behind.
PS.. a good example of the whole usercontrol setup can be downloaded here..
http://www.asp.net/downloads/starter-kits/time-tracker/