Hi,
i have written a script to collect menu paths from a menu in a silverlight application. The menus are shown\added on demand to the menu tree (when someone hovers or click the parent menu, only then sub menus are loading to the DOM tree), so i need to refresh the DOM tree at regular interval. One more thing to note that the size of DOM also getting increased as we going on opening new menus and their sub menus.
Below is the code i am using to collect the menu paths.
01.
/// <summary>
02.
/// Find all available menu paths.
03.
/// </summary>
04.
/// <returns>Returns collected menu paths.</returns>
05.
public
override
List<MenuPath> CollectPaths()
06.
{
07.
List<FrameworkElement> mainMenuItems = RootElement.Find.AllByExpression(
new
XamlFindExpression(
"xamltag=oatimiddleclickmenuitem"
)).ToList();
08.
List<MenuPath> menuPaths =
new
List<MenuPath>();
09.
menuPaths = CollectMenuPaths(filteredMenuItems, MenuPath.EmptyPath, 1);
10.
return
menuPaths;
11.
}
12.
13.
/// <summary>
14.
/// Collect menu paths by finding the controls inside the DOM tree.
15.
/// </summary>
16.
/// <param name="menuItems">Collection of main menu items.</param>
17.
/// <param name="currentPath">current path.</param>
18.
/// <param name="menuPaths">collection of collected menu paths.</param>
19.
/// <returns></returns>
20.
private
List<MenuPath> CollectMenuPaths(List<FrameworkElement> menuItems, MenuPath currentPath,
int
level)
21.
{
22.
List<MenuPath> pathList =
new
List<MenuPath>();
23.
foreach
(FrameworkElement menuListItem
in
menuItems)
24.
{
25.
FrameworkElement menuItemTextBlock = menuListItem.Find.ByExpression(
new
XamlFindExpression(
"xamlTag=grid"
,
"|"
,
"xamlTag=textblock"
));
26.
if
(menuItemTextBlock !=
null
&& !
string
.IsNullOrEmpty(menuItemTextBlock.TextLiteralContent))
27.
{
28.
if
(menuItemTextBlock.TextLiteralContent ==
"MRTU"
)
29.
{
30.
Console.WriteLine(
"Mine"
);
31.
}
32.
MenuPath currentMenuPath = currentPath.Append(
new
MenuId(menuItemTextBlock.TextLiteralContent));
33.
FrameworkElement expandIcon = menuListItem.Find.ByExpression(
new
XamlFindExpression(
"xamlTag=path"
,
"name=#ExpandIconBackground|ExpandIconForeground"
));
34.
if
(level == 1 || expandIcon !=
null
)
35.
{
36.
menuListItem.EnsureClickable();
37.
menuListItem.User.HoverOver();
38.
Playback.Wait(100);
39.
Plugin.OwnerApp.RefreshVisualTrees();
//Refreshing silverlight visual tree.
40.
Playback.Wait(100);
41.
menuListItem.Refresh();
42.
}
43.
List<FrameworkElement> innerMenuItems = menuListItem.Find.AllByExpression(
new
XamlFindExpression(
"xamltag=oatimiddleclickmenuItem"
)).ToList();
44.
if
(innerMenuItems.Count > 0)
45.
{
46.
pathList.AddRange(CollectMenuPaths(innerMenuItems, currentMenuPath, level + 1));
47.
}
48.
else
49.
{
50.
pathList.Add(currentMenuPath);
51.
}
52.
}
53.
}
54.
return
pathList;
55.
}
Its working fine for me when we have small menus (let say less then 500 menu paths under the main menu). But when we have larger menus (say more then 500 to 5000 menu paths under the main menu) ,
In that case in the start of the menu scraping it works fine, but as we progressing its performance getting worsts (as DOM tree size also increasing simultaneously) and at a certain point it throwing me : "OutOfMemoryException" in System.dll at line no - 41 (menuListItem.Refresh()).
I tried to copy the Visual Tree at the time of exception and found that the size of visual tree text is of 2.5MB file.
Note : I am runiing it on a dedicated automated system with 16GB of memory.so i have enough memory for this. This script is a part of our regression solution, so we have to run it over on any system whether large or small. i want to make it such that it can work on a large menu as well.
Please look into this ASAP.
Thanks & Regards
Vinay