Read text from textbox in Coded UI Tests - winforms

There is a bug/limitation in the Coded UI Test WinEdit class: when overriding the OnKeyDown method or subscribing to the KeyDown event in a text box, it is not possible to use the WinEdit.Text property.
That is, when you have this...
private void myTextbox_KeyDown(object sender, KeyEventArgs e)
{
// ...
}
...this won't work:
var edit = new WinEdit(ancestor);
edit.SearchProperties[WinControl.PropertyNames.ControlName] = "myTextbox";
edit.Text = "New value"; // This doesn't work
I've found a work-around for setting the value here:
var edit = new WinEdit(ancestor);
edit.SearchProperties[WinControl.PropertyNames.ControlName] = "myTextbox";
Mouse.Click(edit);
System.Windows.Forms.SendKeys.SendWait("New value");
My question: does anyone know a work-around for reading the value?
var edit = new WinEdit(Window);
edit.SearchProperties[WinControl.PropertyNames.ControlName] = "myTextbox";
string actual = edit.Text; // This doesn't work

I found a work-around myself:
[DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
public static extern bool SendMessage(IntPtr hWnd, int msg, int wParam, StringBuilder lParam);
const int WM_GETTEXT = 0x000D;
var edit = new WinEdit(Window);
edit.SearchProperties[WinControl.PropertyNames.ControlName] = "myTextbox";
var sb = new StringBuilder(1024);
SendMessage(edit.WindowHandle, WM_GETTEXT, sb.Capacity, sb);
string actual = sb.ToString();

The Solution is :
Suppose you have one window form having one text box.
//Launch your Application
ApplicationUnderTest mainWindow =
ApplicationUnderTest.Launch(#"D:\Samples\YourApplication.exe");
//Search Text box in your windows Form
var username = new WinWindow(mainWindow);
username.SearchProperties[WinControl.PropertyNames.ControlName] = "txtUserName";
//To Set Text or get, Initialize WinEdit object and asign searched object username to WinEdit object editUsername
WinEdit editUsername = new WinEdit(username) {Text = "Pakistan"};
//get text from textbox username
string text = editUserName.Text;
Thanks,

Related

How to clear ComboBox text when DropdownStyle is DropDown

I have a ComboBox whose DropdownStyle is DropDown. So, I can select from the list or can type own data.
When I click on the clear button, text typed in the ComboxBox should be removed.
I have already tried "object.text = string.Empty;" but not working.
public ComboBox cmb_Identifier(int x, int y)
{
cntrlObjList.comboBoxIdentifier.Items.Clear();
cntrlObjList.comboBoxIdentifier.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDown;
cntrlObjList.comboBoxIdentifier.FormattingEnabled = true;
cntrlObjList.comboBoxIdentifier.Location = new System.Drawing.Point(x, y);
cntrlObjList.comboBoxIdentifier.Name = "cmbIdentifier";
cntrlObjList.comboBoxIdentifier.Size = new System.Drawing.Size(151, 21);
cntrlObjList.comboBoxIdentifier.TabIndex = 6;
cntrlObjList.comboBoxIdentifier.Visible = true;
cntrlObjList.comboBoxIdentifier.Items.Add("Identifier 1");
cntrlObjList.comboBoxIdentifier.Items.Add("Identifier 2");
return cntrlObjList.comboBoxIdentifier;
}
public void btnClear_Click(object sender, EventArgs e)
{
cntrlObjListMain.comboBoxIdentifier.SelectedText = string.Empty(); //not working
}
I found the solution and it is working in my case.
cntrlObjList.comboBoxIdentifier.Text = null;
The following should work for you
cntrlObjList.comboBoxIdentifier.Text = String.Empty;
or
cntrlObjList.comboBoxIdentifier.Text = "";

datagridview control continues update, gui flickers when scrolling window

Problem:
I have a Winform application with a form en on this form i have a databound DataGridView.
The datagridview is updated from the backend by updating the bind object continuesly using a timer to get the data every 10 seconds. In order to update the gui with this new data i call a RefreshDatabindings. (if i do not do this, the gui is nog updated, i am binding to a BindingList and the object implement the INotifyPropertyChanged)
When the form is big enough to show the whole datagridview at once everything is working wel. But when the form is not big enough to show the hole datagridview a scrollbar appears.
When i scroll to the right to see the rest of the datagridview i see the gui flickering (only the part that wasn't visible before scrolling). When i strech the form to make de gridview fitting again, everything is working wel (no flashing and flickering). the flickering only happens when i have to scroll.
I am lost, can please somebody help me :)?
I allready tryed the DoubleBuffered = true.
Thanks in advance!
BindingList<InstanceTableViewModel> viewModelList;
public Form1()
{
InitializeComponent();
DoubleBuffered = true;
functionParamList = new List<FunctionParameter>();
functionParamList.Add(new FunctionParameter { DeviceValue = 100, InstanceId = "1", Name = "A" });
functionParamList.Add(new FunctionParameter { DeviceValue = 200, InstanceId = "2", Name = "B" });
functionParamList.Add(new FunctionParameter { DeviceValue = 300, InstanceId = "3", Name = "C" });
viewModelList = CreateInstanceTableViewModelList();
dataGridView1.DataSource = viewModelList;
//Create timer
updateDataTimer = new System.Timers.Timer();
updateDataTimer.Interval = 500;
updateDataTimer.Elapsed += updateDataTimer_Elapsed;
updateDataTimer.Start();
}
private void updateDataTimer_Elapsed(object sender, ElapsedEventArgs e)
{
ThreadPool.QueueUserWorkItem(ReadDataThreadPoolMethod);
}
private void ReadDataThreadPoolMethod(object state)
{
Random random = new Random();
int randomNumber = random.Next(0, 100);
foreach (FunctionParameter param in functionParamList)
{
param.DeviceValue = Convert.ToInt64(randomNumber);
}
}
void functionParameter_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
var functionParameter = sender as FunctionParameter;
var propertyName = e.PropertyName;
var propertyValue = functionParameter.DeviceValue;
var parameterName = functionParameter.Name;
UpdateViewModel(functionParameter.InstanceId, propertyName, propertyValue, parameterName);
}
private void UpdateViewModel(string instanceId, string propertyName, long propertyValue, string parameterName)
{
var instanceViewModel = viewModelList.Single(x => x.InstanceId == instanceId && x.NameLabel == parameterName);
if (instanceViewModel != null)
{
instanceViewModel.ValueHex = Convert.ToUInt16(propertyValue);
}
ResetBindingsSource();
}
delegate void UpdateBindingsInvoker();
public void ResetBindingsSource()
{
if (!this.IsDisposed)
{
if (this.InvokeRequired)
{
this.Invoke(new UpdateBindingsInvoker(UpdateDataGrid));
}
else
{
UpdateDataGrid();
}
}
}
private void UpdateDataGrid()
{
dataGridView1.Refresh();
}
So here my solution:
You only uses the Forms DoubleBuffering, but the following code is an extension method to the DataGridview and successfully works (at my tests ;)
public static void DoubleBuffered(this DataGridView dgv, bool setting)
{
Type dgvType = dgv.GetType();
PropertyInfo pi = dgvType.GetProperty("DoubleBuffered",
BindingFlags.Instance | BindingFlags.NonPublic);
pi.SetValue(dgv, setting, null);
}
I found this code right here at Codeprojct.
You can use it in this way:
YourDataGridView.DoubleBuffered(true);
I hope i could help you ^^

set ItemContainerStyle from code

I am working on a custom wpf control which is derived from a ListBox and am trying to apply some formatting to a custom property.
When a particular custom property is false, I want to apply some formatting to the ListBox.
I am using the following code to attempt to apply the styling -
var t = new Trigger();
var BackgroundSetter = new Setter {Property = BackgroundProperty, Value = null};
var BrushSetter = new Setter { Property = BorderBrushProperty, Value = null };
t.Setters.Add(BackgroundSetter);
t.Setters.Add(BrushSetter);
var s = new Style(typeof(ListBox));
s.Triggers.Add(t);
editor.ItemContainerStyle.Triggers.Add(t);
I have also tried the following with no luck -
editor.ItemContainerStyle = s;
I am getting an error that indicates that some object was not initialized and stepping through shows that editor.ItemContainerStyle is null.
The actual error message just says Exception has been thrown by the target of an invocation.
Does anyone have any idea what I might be doing wrong?
Thanks
I was able to get this working - below is the code that I actually ended up using -
public bool IsSelectable
{
get { return (bool)GetValue(IsSelectableProperty); }
set { SetValue(IsSelectableProperty, value); }
}
public static DependencyProperty IsSelectableProperty = DependencyProperty.Register("IsSelectable", typeof(bool), typeof(ListEditor), new FrameworkPropertyMetadata(true, new PropertyChangedCallback(IsSelectablePropertyChanged)) { BindsTwoWayByDefault = true });
private static void IsSelectablePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var editor = sender as ListEditor;
var s = new Style(typeof(ListBoxItem));
var enableSetter = new Setter {Property = IsEnabledProperty, Value = editor.IsSelectable};
s.Setters.Add(enableSetter);
editor.ItemContainerStyle = s;
}

How can set MaxLength for TreeNode Name and text property?

How can set MaxLength for TreeNode Name and text property? This is a windows forms application, where user right clicks a treeview to add a node and the maxlength of the treenode name should be 40 chars. Currently I check this in AfterlabelEdit event, and throw a message if no. of chars exceeds. But the requiremnet says to limit the length without showing the message box as we do in textboxes.
Thanks.
You could display a text box over the treeview and set the MaxLength on that.
One way to do that is create a text box with the form:
private TextBox _TextBox;
public Form1()
{
InitializeComponent();
_TextBox = new TextBox();
_TextBox.Visible = false;
_TextBox.LostFocus += new EventHandler(_TextBox_LostFocus);
_TextBox.Validating += new CancelEventHandler(_TextBox_Validating);
this.Controls.Add(_TextBox);
}
private void _TextBox_LostFocus(object sender, EventArgs e)
{
_TextBox.Visible = false;
}
private void _TextBox_Validating(object sender, CancelEventArgs e)
{
treeView1.SelectedNode.Text = _TextBox.Text;
}
Then in the tree view BeforeLabelEdit set the MaxLength of the text box and show it over the currently selected Node:
private void treeView1_BeforeLabelEdit(object sender, NodeLabelEditEventArgs e)
{
_TextBox.MaxLength = 10;
e.CancelEdit = true;
TreeNode selectedNode = treeView1.SelectedNode;
_TextBox.Visible = true;
_TextBox.Text = selectedNode.Text;
_TextBox.SelectAll();
_TextBox.BringToFront();
_TextBox.Left = treeView1.Left + selectedNode.Bounds.Left;
_TextBox.Top = treeView1.Top + selectedNode.Bounds.Top;
_TextBox.Focus();
}
You'll probably want to add some additional functionality to the text box so it sizes correctly based on the width of the tree view and also so it accepts the new text on the user hitting return, etc.

How do I access a MessageBox with white?

I have a simple message box in a WPF application that is launched as below:
private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Howdy", "Howdy");
}
I can get white to click my button and launch the message box.
UISpy shows it as a child of my window I couldn't work out the method to access it.
How do I get access to my MessageBox to verify its contents?
Found it! The window class has a MessageBox method that does the trick:
var app = Application.Launch(#"c:\ApplicationPath.exe");
var window = app.GetWindow("Window1");
var helloButton = window.Get<Button>("Hello");
Assert.IsNotNull(helloButton);
helloButton.Click();
var messageBox = window.MessageBox("Howdy");
Assert.IsNotNull(messageBox);
Please try this
Window messageBox = window.MessageBox("");
var label = messageBox.Get<Label>(SearchCriteria.Indexed(0));
Assert.AreEqual("Hello",label.Text);
Contained in the White source code are some UI tests projects (to test White itself).
One of the test includes MessageBox tests, which includes a way to obtain the displayed message.
[TestFixture, WinFormCategory, WPFCategory]
public class MessageBoxTest : ControlsActionTest
{
[Test]
public void CloseMessageBoxTest()
{
window.Get<Button>("buttonLaunchesMessageBox").Click();
Window messageBox = window.MessageBox("Close Me");
var label = window.Get<Label>("65535");
Assert.AreEqual("Close Me", label.Text);
messageBox.Close();
}
[Test]
public void ClickButtonOnMessageBox()
{
window.Get<Button>("buttonLaunchesMessageBox").Click();
Window messageBox = window.MessageBox("Close Me");
messageBox.Get<Button>(SearchCriteria.ByText("OK")).Click();
}
}
Evidently, the label used to display the text message is owned by the window displaying the messagebox, and its primary identification is the max word value (65535).
window.MessageBox() is a good solution!!
But this method would stuck for a long time if the messagebox doesn't appear. Sometimes I want to check "Not Appearance" of a messagebox (Warning, Error, etc.). So I write a method to set the timeOut by threading.
[TestMethod]
public void TestMethod()
{
// arrange
var app = Application.Launch(#"c:\ApplicationPath.exe");
var targetWindow = app.GetWindow("Window1");
Button button = targetWindow.Get<Button>("Button");
// act
button.Click();
var actual = GetMessageBox(targetWindow, "Application Error", 1000L);
// assert
Assert.IsNotNull(actual); // I want to see the messagebox appears.
// Assert.IsNull(actual); // I don't want to see the messagebox apears.
}
private void GetMessageBox(Window targetWindow, string title, long timeOutInMillisecond)
{
Window window = null ;
Thread t = new Thread(delegate()
{
window = targetWindow.MessageBox(title);
});
t.Start();
long l = CurrentTimeMillis();
while (CurrentTimeMillis() - l <= timeOutInMillsecond) { }
if (window == null)
t.Abort();
return window;
}
public static class DateTimeUtil
{
private static DateTime Jan1st1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public static long currentTimeMillis()
{
return (long)((DateTime.UtcNow - Jan1st1970).TotalMilliseconds);
}
}

Resources