I am using coded ui test with my windows store app.
My control hierarchy is :
UIPearsonPOCCommonViewFlipViewItem (XAMLFlipViewItem - > UIWebViewPane (XAMLWebViewPane) - > Rest of the content.
For rest of the child controls, there is no specific automation id or unique names and they look like html control for e.g. refer the image appended.
I want to iterate over the children of UIWebViewPane and reach to child DIV which is having the innerText.
I am relatively very new to coded ui test. I am unable to iterate over the children of UIWebViewPane(XAMLWebViewPane)
If the child control's inner text is unique, you could always search on that using the parent control in the definition. Ex:
public HtmlControl child()
{
HtmlControl parent = new HtmlControl(browser);
parent.SearchProperties["id"] = "[my id]";
HtmlControl child = new HtmlControl(parent);
child.SearchProperties["innerText"] = "[the inner text]";
return child;
}
If you truly want to iterate through, then you'll have to crawl the structure using the .GetParent() and .GetChildren() methods of the UITestControl class.
public HtmlControl child()
{
//First, we create an empty HtmlControl to return.
HtmlControl result = new HtmlControl()
//Specify the parent and get a collection of the children (this only goes one level,
// so if you have to go deeper, you'll have to nest your foreach loops and get
// children of the children, etc.
HtmlControl parent = new HtmlControl(browser);
parent.SearchProperties["id"] = "[my id]";
UITestControlCollection children = parent.GetChildren();
foreach (UITestControl child in children)
{
// If the child has the text you're looking for, then assign it to the result
// object and break the loop.
if (child.GetProperty("InnerText").ToString().Equals(searchTerm))
{
result = (HtmlControl)child;
break;
}
}
return result;
}
Personally, I'd try the first option. Your best bet, though, is to ask (politely) for the developer to add some unique and static tags to the HTML.
Related
I have a Control which is first children of the Parent but nothing is unique in Parent and in the Control. I can find unique properties for Scond children so I need to find the previous Sibling of Second children
This is possible by using the SearchConfiguration property on the control.
What you do is you search for the label and next you instantiate a WinEdit control and pass it in the label search control. Next you set on the WinEdit instance the SearchConfiguration.Add(SearchConfiguration.NextSibling)
this will now search for the next sibling of the text label.
in a code example this looks like follows:
var app = ApplicationUnderTest.Launch(#"yourapplication.exe");
var mainWindow = new WinWindow(app);
mainWindow.WindowTitles.Add("Form1");
WinText textLabel = new WinText(mainWindow);
textLabel.SearchProperties.Add(WinControl.PropertyNames.Name, "Some Text Label");
WinEdit siblingEditControl = new WinEdit(textLabel);
siblingEditControl.SearchConfigurations.Add(SearchConfiguration.NextSibling);
siblingEditControl.Text = "setting the text";
There are no direct methods for getting siblings. One way of finding the siblings of a control is to find its parent and then find all the children of that parent. Next search through the children to find the current control and then take the previous one. The method might be based on the following. It uses the Name fields of the control for the comparison, this may be incorrect for the general case and I suggest other values be tried.
public UITestControl GetPreviousSibling(UITestControl uitc)
{
UITestControlCollection siblings = uitc.GetParent().GetChildren();
// Note that 'sibings[0]' has no predecessor
for (int ii=1; ii<siblings.Count)
{
if (uitc.Name == siblings[ii].Name)
{
return siblings[ii - 1];
}
}
return null;
}
The definition of "sibling" is not clear. This MSDN blog gives some details of siblings.
I have a method that is used as a threadsafe callback to update a treeview. It takes two string parameters. The first is the passed data and the second is the IP of the host it checked.
I am trying to check whether or not the treeview currently contains the string containing the input string and if it doesn't than it is supposed to add it to the treeview as a parent node, then add the ip string underneath as a child. Although if it does already contain that input string as a parent node than it should add only the Ip address underneath the parent that the data string matches. So it basically sorts the ips. Each parent node will have multiple ips underneath.
My issue is that my method is adding each string as it's own parent regardless if it is a duplicate, which also means that it is not adding the IP of the duplicate input underneath the parent. Can anyone take a look and see where I am going wrong?
public void UpdateScan(string input, string ip)
{
lock (outputTree)
{
outputTree.BeginUpdate();
if (!(outputTree.Nodes.ContainsKey(input)))
{
TreeNode treeNode = new TreeNode(input);
//Add our parent node
outputTree.Nodes.Add(treeNode);
//Add our child node
treeNode.Nodes.Add(ip);
}
else
{
TreeNode[] treeNode = outputTree.Nodes.Find(input, true);
//Add only child node
foreach (var node in treeNode)
{
node.Nodes.Add(ip);
}
}
outputTree.EndUpdate();
}
}
I was able to get it working. By dynamically adding a key containing the data to the parent node, so I can then use that key to find the parents to add the correct children to them.
public void UpdateScan(string input, string ip)
{
lock (outputTree)
{
outputTree.BeginUpdate();
if (! outputTree.Nodes.ContainsKey(input))
{
TreeNode treeNode = new TreeNode(input);
treeNode.Name = input;
//Add our parent node
outputTree.Nodes.Add(treeNode);
//Add our child node
treeNode.Nodes.Add(ip);
}
else
{
TreeNode[] found = outputTree.Nodes.Find(input, true);
TreeNode newChild = new TreeNode(ip);
//Add only child node
found[0].Nodes.Add(newChild);
}
outputTree.EndUpdate();
}
}
I have a TreeView in my Windows Form user interface.
I want to fill it up from a database, but it does not refresh ever, even though if I WriteLine() every node, it is in memory as I expect.
In order to make it more easy to understand, I wrote a little example program that only has one button that creates a TreeView and a TreeView called treeView1 to display its content.
If anyone can tell me where I have misunderstood the use of the TreeView, it would be a tremendous help.
private void button1_Click(object sender, EventArgs e)
{
// create a tree
TreeView t = new TreeView();
TreeNode[] child = new TreeNode [1];
child[0]=new TreeNode("myCat");
child[0].Name = "IndependantOne";
TreeNode categoryNode = new TreeNode("catIdTag", child);
categoryNode.Name = "Citizen Cat 5239002147";
t.Nodes.Add(categoryNode);
// some stuff under the first node
TreeNode[] mouseNode = new TreeNode[1];
mouseNode[0] = new TreeNode("myMouse");
mouseNode[0].Name = "SqueakyOne";
TreeNode[] childItem = new TreeNode[1];
childItem[0] = new TreeNode("mouseIdTag", mouseNode);
childItem[0].Name = "Citizen Mouse 54655654649";
TreeNode eltNode = new TreeNode("Cheese", childItem);
eltNode.Name = "Emmental";
t.Nodes["Citizen Cat 5239002147"].Nodes.Add(eltNode);
// fill in the winform treeview
if (t != null)
{
//treeView1.Visible = false;
treeView1.BeginUpdate();
treeView1.Nodes.Clear();
treeView1.TopNode = t.TopNode;
foreach (TreeNode n in t.Nodes)
{
treeView1.Nodes.Add(n);
System.Diagnostics.Debug.WriteLine("Category Node contains: " + treeView1.Nodes[n.Name].Name + " at " + treeView1.Nodes[n.Name].Level);
foreach (TreeNode no in treeView1.Nodes[n.Name].Nodes)
{
System.Diagnostics.Debug.WriteLine("Category Node Nodes contains: " + no.Name);
}
}
/*
This part I tried and it doesn't work either, still add it in the question if anyone knows if it's wiser?
this.treeView1 = t;
this.treeView1.Location = new System.Drawing.Point(233, 12);
this.treeView1.Name = "treeView1";
this.treeView1.Size = new System.Drawing.Size(351, 277);
this.treeView1.TabIndex = 11;
this.treeView1.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeView1_AfterSelect);
*/
treeView1.EndUpdate();
this.treeView1.Update();
this.treeView1.Refresh();
treeView1.Show();
//this.Refresh();
}
}
I also tried setting the treeView1 with
treeView1 = t;
It was not a success...
change
treeView1.Nodes.Add(n);
with
treeView1.Nodes.Add((TreeNode)n.Clone());
You cannot host the same node in more than one TreeView control.
Alternatively, you can remove nodes from source TreeView before adding them to other TreeView:
while(t.Nodes.Count != 0)
{
var node = t.Nodes[0];
t.Nodes.RemoveAt(0);
treeView1.Nodes.Add(node);
}
And I hope that there is a real reason why you create and fill tree view in your method instead of directly filling an already existing one. If it is not an intended behavior, remove the if block completely and change TreeView t = new TreeView(); to var t = treeView1.
This behavior is expected because with this code you`re confusing node-to-treeview relationship nature of the native .NET treeview control. Instead when moving nodes between treeviews (t -> treeView1) you need to clone them as suggested. Without that moved node still linked with the old treeview (see node.Treeview property) and because original tree (t) is not visible/added to any parent (form), I guess node will be invisible as well.
Also, the way you`re working with data loading (through creating new treeview) is pretty bad pattern. Instead you need to download your data (async I guess) into a temp buffer and recreate the treeView1 at once when data will be available with BeginUpdate/EndUpdate calls.
PS. Replacing treeView1 variable with 't' won't work as well because you don't replace the treeview control instance in the parent form/panel Controls property with this code.
Example code:
var div = new HtmlGenericControl("div");
div.Controls.Add(new Literal() { ID = "litSomeLit" });
var lit = (Literal)div.FindControl("litSomeLit");
Assert.IsNotNull(lit);
This code fails the assert, because lit is null. Debugging shows that div.Controls definitely contains a literal with ID of "litSomeLit." My questions are "Why?" and "Is there any way to get a control of a specific ID without doing a recursive search of div.Controls[] by hand one element at a time?"
The reason I'm doing things this way is that my actual application is not so straightforward- a method I'm writing is given a complex control with several subcontrols in a number of possible configurations. I need to access a specific control several layers down (eg, the control with ID "txtSpecificControl" might be at StartingControl.Controls[0].Controls[2].Controls[1].Controls[3]). Normally I could just do FindControl("txtSpecificControl"), but that does not seem to work when the controls were just dynamically created (as in the above example code).
Near as I can tell, there is no way to do what I'm trying to accomplish without adding the control to the page. If I had to guess, I'd say that FindControl uses the UniqueID property of the control, which generally contains the IDs of all the controls above the current one (eg OuterControlID$LowerControlId$TargetControlID). That would only get generated when the control actually gets added to the page.
Anyway, here's an implementation of recursive depth-first-search FindControl that'll work when the control is not attached to the page yet:
public static Control FindControl(Control parent, string id)
{
foreach (Control control in parent.Controls)
{
if (control.ID == id)
{
return control;
}
var childResult = FindControl(control, id);
if (childResult != null)
{
return childResult;
}
}
return null;
}
Change your code to
var div = new HtmlGenericControl("div");
Page.Controls.Add(div);
div.Controls.Add(new Literal() { ID = "litSomeLit" });
var lit = (Literal)div.FindControl("litSomeLit");
As far as i know FindControl only works when the control is in the visual tree of the page.
When you confirmed that the control was in the Controls collection, did you do that by inspecting the collection directly? FindControl() may not work in this context.
When you debug the test, is the var lit null? If so, you may have to access the member by item index instead of using the FindControl() method.
I have a user control in which I need to return child nodes based on parentID. I am able to get the parentID, but don't know the syntax for returning child nodes.
Getting child nodes is pretty straightforward.
Not sure how far you are with your code so here's a complete example with the various options:
using umbraco.presentation.nodeFactory;
namespace cogworks.usercontrols
{
public partial class ExampleUserControl : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
//If you just want the children of the current node use the following method
var currentNode = Node.GetCurrent();
//If you need a specific node based on ID use this method (where 123 = the desired node id)
var specificNode = new Node(123);
//To get the children as a Nodes collection use this method
var childNodes = specificNode.Children;
//Iterating over nodes collection example
foreach(var node in childNodes)
{
Response.Write(string.Format("{0}<br />", node.Name));
}
//To get the nodes as a datatable so you can use it for DataBinding use this method
var childNodesAsDataTable = node.ChildrenAsTable();
//Databind example
GridViewOnPage.DataSource = childNodesAsDataTable;
GridViewOnPage.DataBind();
}
}
}