I have a ui coded ui test in visual studio 2010.
I want to write a code which will:
Discover all the controls on a window and child windows which are button, grid, label
write a uimap with the id which is the name of the control in the code.
For starting it, I've write the following:
public void CodedUITestMethod1()
{
string uiTestFileName = #"D:\dev11\ConsoleApplication1\TestProject1\UIMap.uitest";
UITest uiTest = UITest.Create(uiTestFileName);
Microsoft.VisualStudio.TestTools.UITest.Common.UIMap.UIMap newMap = new Microsoft.VisualStudio.TestTools.UITest.Common.UIMap.UIMap();
newMap.Id = "UIMap";
uiTest.Maps.Add(newMap);
GetAllChildren(BrowserWindow.Launch(new Uri("http://bing.com")), uiTest.Maps[0];);
uiTest.Save(uiTestFileName);
}
private void GetAllChildren(UITestControl uiTestControl, Microsoft.VisualStudio.TestTools.UITest.Common.UIMap.UIMap map)
{
foreach (UITestControl child in uiTestControl.GetChildren())
{
map.AddUIObject((IUITechnologyElement)child.GetProperty(UITestControl.PropertyNames.UITechnologyElement));
GetAllChildren(child, map);
}
}
But it insert into the recursive loop and doesn't end it.
Can anyone help me?
I think that to avoid possible infinite recursion you have to add this code:
private void GetAllChildren(UITestControl uiTestControl, Microsoft.VisualStudio.TestTools.UITest.Common.UIMap.UIMap map)
{
foreach (UITestControl child in uiTestControl.GetChildren())
{
IUITechnologyElement tElem=(IUITechnologyElement)child.GetProperty(UITestControl.PropertyNames.UITechnologyElement);
if (!map.Contains(tElem))
{
map.AddUIObject(tElem);
GetAllChildren(child, map);
}
}
}
This way you avoid to consider the same object multiple times and keep away from possible visual tree cycle.
Before you call map.AddUIObject and GetAllChildren in the foreach loop, check to make sure the object doesn't already exist in the map collection.
Check that the child has children before calling GetAllChildren(child, map)
if(child.HasChildren) {
GetAllChildren(child, map);
}
Related
I'm trying to create a method to close all child forms in windows application C#.
There are no errors but it doesn't work in runtime!
private void closechildform(Form f)
{
foreach (Form frm in this.MdiChildren)
{
frm.SendToBack();
frm.Hide();
return;
}
}
You should move the return to outside the foreach loop. Because in your existing code it will return after first iteration.
FYI: If the method is void then there’s no need of return inside the method.
private void CheckingSelection() {
Transform child = Selection.activeTransform;
Transform[] patchesTransform = builder.GetLevelEditorPatchesTransform();
foreach (var parent in patchesTransform) {
if (child.IsChildOf(parent) && child != parent) {
Debug.Log("Set active " + parent.gameObject);
Selection.activeGameObject = parent.gameObject;
}
}
}
That's what I do, but it does not select the parent. What am I do wrong ?
The deal is how I called method CheckingSelection();
I added this method to delegate Selection.selectionChanged. And I thought its kind of logical things to do my checking after selecting something. But it was not working. It might be of internal Unity things, that block recursy or some.
So, I addedCheckingSelection() method to EditorApplication.update delegate, and it works.
I have the following code:
void Setup(CityBuilding[] buildings) {
foreach (CityBuilding building in buildings)
{
GameObject buildingDisp = Instantiate(singleGoodsDisplay);
//... Other stuff not relevent happens here
buildingDisp.GetComponent<Button>().onClick.AddListener(() => { ProcessClick(building); });
Debug.Log(building);
}
}
private void ProcessClick(CityBuilding building)
{
Debug.Log(building);
}
The bottom line is, I have a few buttons that are saved as a prefab and instantiated. I'm adding an onClick Listener to it, in the form of a lambda function. I'm passing in a data object. Right now buildings is an array of two. I see that both items are debugged, however, when I actually click on the buttons, I always see the second item is used, never the first. I'm not quite sure what I'm doing wrong. Any thoughts? Thanks!
It seems that the object reference isn't saved, it only uses the latest. What does work is to save a copy and pass it, as follows:
void Setup(CityBuilding[] buildings) {
foreach (CityBuilding building in buildings)
{
CityBuilding temp=building;
GameObject buildingDisp = Instantiate(singleGoodsDisplay);
//... Other stuff not relevent happens here
buildingDisp.GetComponent<Button>().onClick.AddListener(() => { ProcessClick(temp); });
}
}
Lately, I received a bug report for Ninject.Web that it is not working properly together with ASP.NET dynamic data. The problem is that on postback (e.g. when Inserting, Deleting, Editing a record) the table is not shown anymore.
Some debuging showed that the problem is caused by a IHttpModule that recursively iterates through all controls of a page after it is initialized. As soon as this module accesses the Controls property get accessor of FormView or GridView the problem occurs. If this type of controls is skiped everything is fine. The following code shows the module:
public class NinjectHttpModule : DisposableObject, IHttpModule
{
private HttpApplication httpApplication;
public void Init(HttpApplication context)
{
this.httpApplication = context;
this.httpApplication.PreRequestHandlerExecute += this.OnPreRequestHandlerExecute;
}
private static void InjectUserControls(Control parent)
{
if (parent == null)
{
return;
}
foreach (Control control in parent.Controls)
{
if (control is UserControl)
{
// KernelContainer.Inject(control); This is irrelevant for the question.
}
InjectUserControls(control);
}
}
private void OnPreRequestHandlerExecute(object sender, EventArgs e)
{
var page = this.httpApplication.Context.CurrentHandler as Page;
if (page == null)
{
return;
}
KernelContainer.Inject(page);
page.InitComplete += (src, args) => InjectUserControls(page);
}
}
If this code is changed so that the iteration through the child controls of DataBoundControls is delayed to the DataBound event everything is fine. Shown by the next code snippet:
private static void InjectUserControls(Control parent, bool skipDataBoundControls)
{
if (parent == null)
{
return;
}
if (skipDataBoundControls)
{
var dataBoundControl = parent as DataBoundControl;
if (dataBoundControl != null)
{
dataBoundControl.DataBound += InjectDataBoundControl;
return;
}
}
foreach (Control control in parent.Controls)
{
if (control is UserControl)
{
KernelContainer.Inject(control);
}
InjectUserControls(control, skipDataBoundControls);
}
}
private static void InjectDataBoundControl(object sender, EventArgs e)
{
var dataBoundControl = sender as DataBoundControl;
if (dataBoundControl != null)
{
dataBoundControl.DataBound -= InjectDataBoundControl;
InjectUserControls(dataBoundControl, false);
}
}
Because I'm completely unfamiliar with System.Web.DynamicData I'd like to know some things to get a better feeling about how to fix this bug:
Why does this problem occur? I mean it's only a simple read access to the Controls property.
What side effects can the change above have?
Is it still early enough to inject the controls after the data bound event?
Do you think this is a valid bug fix for this problem?
Certainly puzzling behavior, as can sometimes happen in WebForms with the many phases of execution.
Even though it's just a simple read access to the Controls property, this property can actually do a lot of work to return the child controls. In particular, it can't return the child controls unless they have been created, and that creation normally does not occur until later in the page life cycle. So by accessing it in InitComplete, the children end up getting created prematurely, before some important Dynamic Data hookups have happened, causing some controls to be missing. Yes, I realize that the end result behavior seems to make little sense, which is why some people favor the straightforwardness of MVC :)
As an alternate possible workaround, could you try moving your injection from InitComplete to PreLoad? e.g.
page.PreLoad += (src, args) => InjectUserControls(page);
I'm pretty sure that'll address the problem, though I'm less sure whether this will cause issues with your KernelContainer.Inject logic. Give it a try, since it's simpler than your workaround.
If that doesn't work, I think your workaround is ok, as it delays the enumeration until the children are created. As for 'Is it still early enough to inject the controls after the data bound event', I think that depends in exactly what KernelContainer.Inject does, and what expectations it has on the state of the control.
I have a compound control contains nested controls. The problem i am facing is that control read properties from a global setting class which is static and intern read from setting file. To stop individual control from accessing configuration in design mode i added check in each control.
If(!DesignMode){
...
//Initialize properties e.g. prop = AppConfig.GetProperty("prop1");
}
The problem is that individual control work fine when open in VS. But when i open top control containing nested control i get error by VS designer. The error is that in a nested control DesignMode=false for some reason.
I also created a test app and created a simple control within another control to test if there is a problem with VS but it seem to work correctly for any depth of controls.
I dont even know how to debug this. For now i comment out the property initializing code and build it and then open designer and there uncomment it and build it again to run it.
Did anyone came across this problem or is there any way to fix it.
The problem you're facing is that the DesignMode is not set while in Constructor (at any level).
Move your initialization methods to Load event, to avoid this problem.
Also, you could add additional comparison with:
protected bool IsInDesignMode
{
get
{
return DesignMode || LicenseManager.UsageMode == LicenseUsageMode.Designtime;
}
}
This would definitely provide an acurate way to determine the design mode because sometimes VisualStudio
returns DesignMode = false while you're placing user controls on the form, or refreshing the form display itself in design.
i do define static bool NotInDesignMode in Program.cs and set it to true in Main()
that way i dont take any dependencies on LicenseManager.UsageMode
however you wouldnt do that if you are writing a generic class lib.
I had same problem.
Maybe this will help you.
protected override void Dispose(bool disposing)
{
if (Application.ExecutablePath.IndexOf("devenv.exe", StringComparison.OrdinalIgnoreCase) < 0)
{
try
{
if (m_NormalImage != null) m_NormalImage.Dispose();
if (m_DownImage != null) m_DownImage.Dispose();
if (m_HoverImage != null) m_HoverImage.Dispose();
m_NormalImage = null;
m_DownImage = null;
m_HoverImage = null;
}
catch
{
}
}
base.Dispose(disposing);
}
I've ran into the problem that the DesignMode flag was set after the Load EventHandler has been invoked. I solved this by writing this extension method which checks if the parent control DesignMode flag has been set.
public static bool InDesignModeSelfOrAncestors(this Control control) {
static bool GetDesignModePropertyValue(Control c) {
if (c.GetType().GetProperty("DesignMode", BindingFlags.Instance | BindingFlags.NonPublic) is {} property) {
return (bool) property.GetValue(c, null);
}
return false;
}
var designModeFlag = GetDesignModePropertyValue(control);
while (control.Parent is {} parent) {
control = parent;
designModeFlag |= GetDesignModePropertyValue(control);
}
return designModeFlag;
}