0

I have a WinForms Dialog with 2 ListBox controls. In the application under test, doubleClicking any items in one of the listbox controls (I'll call this the CONTROL LISTBOX) results in selecting the matching item in the other listbox (SLAVE LISTBOX).

My test causes multiple entries to be made in the CONTROL LISTBOX. The test then performs a ListBox.SelectedItem.DoubleClick() on each of the CONTROL lISTBOX items, comparing the ListBox.SelectedItemText from both listbox controls.

In the application UI, this ALWAYS works, but the test of the call to ListBox.SelectedItemText for SLAVE LISTBOX returns the text matching what is slected in the UI correctly ONLY on the initial iteration of the doubleclick\compare.

Can anybody help me figure out what I'm doing wrong? Thanks!

Here is my code:

public bool SelectMainEventViaErrorEvent(int eventIdx)
{
    bool bSuccess = false;

    errorEvents.Items.Select(eventIdx);
    System.Threading.Thread.Sleep(1000);

    errorEvents.Items.SelectedItem.DoubleClick();
    System.Threading.Thread.Sleep(1000);

    if (eventIdx > 0)
    {
        IVScrollBar vertScroll = mainEvents.ScrollBars.Vertical;
        vertScroll.ScrollDownLarge();
    }

    if (errorEvents.SelectedItemText == mainEvents.SelectedItemText)
    {
        bSuccess = true;
    }

    log.Info($"SelectMainEventViaErrorEvent({eventIdx}) selected error event = {errorEvents.SelectedItemText}");
    log.Info($"SelectMainEventViaErrorEvent({eventIdx}) selected main event = {mainEvents.SelectedItemText}");

    return bSuccess;
}

As you can see, by the following image, the text in both list boxes are identical. However, the call to ListBox.SelectedItemText for the top listbox (SLAVE LISTBOX) returns the value from the first iteration, which matched the first item in the bottom listbox (CONTROL LISTBOX) during the first iteration of the doubleclick/compare.

Proof that the text of the selected listbox items match

Lews Therin
  • 3,707
  • 2
  • 27
  • 53
Jeff H
  • 157
  • 11

2 Answers2

0

Comparing with plain text is bad idea since "Text" != "Text ". What you could use in yor case is DisplayMember and ValueMember properties.

I will demonstrate it for you with manually populating listboxes but you do it from database or however you do it.

First of all create class that will store your values and it's ID's. I usually create it like this (so i am able to use that class later for something else)

public class Int_String
{
    public int _int { get; set; } // Important to be declared like properties and not like variables
    public string _string { get; set; }
}

Now let's populate our listbox like this:

public YourForm()
{
    List<Int_String> list = new List<Int_String>();
    list.Add(new Int_String { _int = 1, _string = "Some text" }); // I am populating it manually but you will populate it from DB or somewhere else
    list.Add(new Int_String { _int = 2, _string = "Some other text" });
    list.Add(new Int_String { _int = 3, _string = "One more text" });

    // Now when we have list we need to bind it to our listbox.

    // IMPORTANT!!!!!
    // Display member and Value member properties SHOULD be able to be added before and after assigning datasource to control (like combobox) BUT for some reason on listbox it only works when you assign it AFTER you bind your datasource to listbox.
    // If you ever work with other controls and use these values, ALWAYS declare display member and value member BEFORE you bind datasource. Why? For now let's just say it is much faster but explanation is for other question

    myListBox1.DataSource = list;
    myListBox1.DisplayMember = "_string"; // When you start typing .DisplayMember, you will not get that property in recommendation since it is hidden so do not think there is not that property there.
    myListBox1.ValueMember = "_int"; // Same as above
}

Now when you populate listbox like this and second one on same way with same id's you could simply do if(listbox1.SelectedValue == listbox2.SelectedValue) and compare them even if their text is not equal but id is.

BONUS: Also what you can do is expand class like this:

public class Int_String
{    
    public int _int { get; set; }
    public string _string { get; set; }

    public string SomethingOther = "AsD";


    public bool IsTrue()
    {
        return true;
    }
}

then bind it on same way and do this:

Int_String item = listbox1.SelectedItem as Int_String;
bool check = item.IsTrue();
MessageBox.Show(item.SomethingOther);

So basically you bind whole class for each item in listbox, display to user one of the variables (in our case _string), set ValueMember to other unique variable so it is easy to search whole listbox and when needed get whole class from that item.

Aleksa Ristic
  • 2,394
  • 3
  • 23
  • 54
  • Thanks, Aleksa! But, the ID's are not the same. In the Event Window WinForm code, when other parts of the main application call into the Event Window form. ALL events go to the SLAVE LISTBOX. If the event to be added is a error event, the event gets added to the SLAVE LISTBOX and the CONTROL LISTBOX. Only error events go to the CONTROL LISTBOX. When the user doubleclicks one of the items in the CONTROL LISTBOX (bottom one), the Event Window form code iterates through the items in the SLAVE LISTBOX (top one) and selects the item that matches the doublelclicked CONTROL LISTBOX item text. – Jeff H Jan 17 '19 at 21:28
  • To maintain that we will do one more thing but you should just show me do code for selecting and adding events to listbox so i do not write for all possible situations. – Aleksa Ristic Jan 18 '19 at 06:28
  • Aleksa, this isn't a WinForm issue. It is the calls in my 'NUnit3.ConsoleRunner' tests where I call 'mainEvents.SelectedItemText'. It only works on the first iteration even though, on all subsequent iterations, the UI on the application under test clearly shows that the text of the selected items in both list boxes are identical. In fact,while the value returned from errorEvents.SelectedItemText is always correct, the value returned from mainEvents.SelectedItemText returns the text from the first iteration on all subsequent iterations even though the correct item is selected in the UI. – Jeff H Jan 21 '19 at 21:32
0

I wasn't ever able to get this working by iterating forward through the errorEvent listbox in my automated test code, but it DOES work when iterating backwards through the errorEvent listbox.

Calling code:

            for (int i = eventViewer.GetErrorEventsCount() - 1; i >= 0; i--)
        {
            bResult = eventViewer.SelectMainEventViaErrorEvent(i);
            if (!bResult)
            {
                break;
            }

            System.Threading.Thread.Sleep(2000);
        }

Verification Code:

        public bool SelectMainEventViaErrorEvent(int eventIdx)
    {
        bool bSuccess = false;
        DisableToolTips(true);

        errorEvents.Select(eventIdx);
        errorEvents.SelectedItem.DoubleClick();

        System.Threading.Thread.Sleep(1000);

        log.Info($"SelectMainEventViaErrorEvent({eventIdx}) selected error event = {errorEvents.SelectedItemText}");
        log.Info($"SelectMainEventViaErrorEvent({eventIdx}) selected main event = {mainEvents.SelectedItemText}");

        if (errorEvents.SelectedItemText == mainEvents.SelectedItemText)
        {
            bSuccess = true;
        }

        return bSuccess;
    }
Jeff H
  • 157
  • 11