C# Gecko Select a Specific ListBox or ComboBox - c#

I using gecko browser and i need select a specific listbox or combobox but same page have in more than one listbox and combobox. I try the following method but it applies to all. And there is no id tag, just a name tag.
GeckoElementCollection ListeBoxKomboBox = Tarayıcı.Document.GetElementsByTagName("option");
foreach (GeckoHtmlElement Element in ListeBoxKomboBox)
{
if (Element.GetAttribute("value") == "1")
{
Element.SetAttribute("selected", "selected");
}
if (Element.GetAttribute("value") == "2")
{
Element.SetAttribute("selected", "selected");
}
}
I do not want you to pick the items with the same value in other boxes. Is this like solution available for gecko?

I notice that there is a label tag ('Turu' or something:)).
So, you can determine which select box is the proper one by:
Select the LI element that has got a first child which content is 'Turu'
Then selecting the 'combobox' inside that LI element
Notice also, that this code is not really right:
GeckoElementCollection ListeBoxKomboBox = Tarayıcı.Document.GetElementsByTagName("option");
You are getting a collection of ALL options in ALL comboboxes on the page. So, the combo box is actually a parent of the option elements (the select element).
Also, option tags are GeckoOptionElements (can be casted safely),
so you can do:
var optionElements= selectBox.GetElementsByTagName("option");
foreach (GeckoOptionElement optionElement in optionElements)
{
if (optionElement.Value == "Foo")
{
optionElement.Selected = true;
}
}
Lastly - yes, the solution like in your link is possible in Gecko.

Related

Display selectedvalues of listbox as label - multiple values

I have got a list box called lstPTLNameDHOD which has multiple PTL names which gets selected using Ctrl. I want to display the selected names in a label or some way that the person submitted the form can see who exactly they are submitting it for.
My problem is I can only get one name to display on the label.
// Items collection
foreach (ListItem item in lstPTLNameDHOD.Items)
{
if (item.Selected)
{
lbl1stPTL.Text = item.Value.ToString();
}
}
This is being called on post back on the reason dropdown being changed.
You are only getting one name to display because your current code would always display name of the last item that is selected.
I don't have a visual studio handy but you could try this:
StringBuilder sbText = new StringBuilder();
// Items collection
foreach (ListItem item in lstPTLNameDHOD.Items)
{
if (item.Selected)
{
lbl1stPTL.Text = sbText.Append(item.Value.ToString()).ToString();
}
}
You can probably refine this by adding a space or a comma between two item names but I hope you get the idea and it helps!
Again, sorry for not having VS handy!

c# select listview item if two listviews contains it

In my program I have 2 listviews and 1 button.
When I press the button, every listview item in the first listview will be selected in the second listview. The items in the first listview always exist in the second listview, but not the other way around.
I'm having trouble with selecting the items in the second listview. I'm trying to get the index with IndexOf.
foreach (ListViewItem item in firstListView.Items)
{
int index = secondListView.Items.IndexOf(item);
secondListView.Items[index].Selected = true;
}
I always get an error that index is -1 when I click the button. And I don't understand what I'm doing wrong.
SOLUTION
So what I tried to do here finding an index of an item which belongs to a different listview, and it doesn't work like that. Even though the text in both listviews are the same, the listview items are not identically the same because they are reference types.
I was not able to use the Text property because items could have the same text. So the solution I had was putting an unique integer in the Tag property for each ListViewItem. Since integers are value types, I can use that integer to check whether the ListViewItem in the first listview is in the second.
// Loop through each item in the first listview
foreach (ListViewItem item1 in firstListView.Items)
{
// For each item in the first listview, loop through the second listview to find if it's there
foreach (ListViewItem item2 in secondListView.Items)
{
// Check if item1 is identical to item2 by looking at its tag
if (int.Parse(item1.Tag) == int.Parse(item2.Tag))
{
// The item has been found and will be selected!
item2.Selected = true;
}
}
}
You can use such linq query to select items of the second list which exist in the first list too:
var items = from i1 in listView1.Items.Cast<ListViewItem>()
from i2 in listView2.Items.Cast<ListViewItem>()
where i1.SubItems.Cast<ListViewItem.ListViewSubItem>()
.Where((s, i) => s.Text != i2.SubItems[i].Text).Count() == 0
select i2;
items.ToList().ForEach(x => { x.Selected = true; });
Note:
When to try to use secondListView.Items.IndexOf method to find an item which belongs to the firstListView you can not expect it to find the item. The item you are trying to find its index, doesn't exists in second listview's item collection. You should find items using Text property of the item and sub items.
Well the same item obviously cant exist in two different lists.
If the text is the same, then try looking by it:
foreach (ListViewItem listViewItem in l1.Items)
{
var item = l2.Items.Cast<ListViewItem>().Where(lvi => lvi.Text == listViewItem.Text);
item.Selected=true;
}
Or:
foreach (ListViewItem listViewItem in l2.Items.Cast<ListViewItem>()
.Where(lvi => l1.Items.Cast<ListViewItem>().Any(lvi2 => lvi.Text == lvi2.Text))
{
listVieItem.Selected=true;
}
IndexOf returns -1 if it cannot find the object passed to it in the list. My guess is that you have an issue with your equality comparison. Do the objects in the lists implement IComparable? Otherwise they may not be finding the items correctly and are reverting to a bad equality comparison. ListViewItem may not be comparing how you expect.
you can try finding the item by text and then get the index like this
foreach (ListViewItem item in firstListView.Items)
{
var itm = secondListView.FindItemWithText(item.Text);
int index = secondListView.Items.IndexOf(itm);
secondListView.Items[index].Selected = true;
secondListView.Select();
}
what FindItemWithText will do is get the item in secondListView which will be of same name as in firstListView and IndexOf will get the index of item in secondListView
Edit
This solution is good when you have two lists whose items are same and does not include any repetition in name else if you have two items in secondListView with same name FindItemWithText will get the first item only.

Cannot Controls.Find a ComboBox inside a GroupBox

On my Visual C# Form application, I have a combobox inside a groupbox to help organize / look neat. However, once I put the combobox inside the groupbox, I am no longer able to find it by looping through all of the controls on my form.
For example, if I run this code with the Combobox inside the Groupbox I get a different result than if its outside the group box:
foreach (Control contrl in this.Controls)
{
richTextBox1.Text += "\n" + contrl.Name;
}
If the combobox is inside the groupbox, it won't find it.
I also noticed in the Form1.Designer.cs file that whenever I add the combobox inside the groupbox, the following line of code appears to the groupbox:
this.groupBox4.Controls.Add(this.myComboBox);
..
this.groupBox4.Location = new System.Drawing.Point(23, 39);
this.groupBox4.Name = "groupBox4";
... etc...
And this line will be removed:
this.Controls.Add(this.myComboBox);
If I try to edit it manually, it automatically switches back once I move the combobox back inside the groupbox.
Any help would be appreciated! Thanks!
Brian
As you said, you added combo box to group box, so it is added to Controls collection of group box and the designer generates this code:
this.groupBox4.Controls.Add(this.myComboBox);
So if you want to find the combo box programmatically, you can use this options:
Why not simply use: this.myComboBox ?
Use var combo = (ComboBox)this.Controls.Find("myComboBox", true).FirstOrDefault();
Use var combo = (ComboBox)this.groupBox4.Controls["myComboBox"]
Also if you want too loop, you should loop over this.groupBox4.Controls using:
foreach(Control c in this.groupBox4.Controls) {/*use c here */}
this.groupBox4.Controls.Cast<Control>().ToList().ForEach(c=>{/*use c here */})
Just like the Form object, the Group object can hold a collection of controls. You would need to iterate through the Group control's controls collection.
One more idea for getting at all or one ComboBox in a GroupBox, in this case groupBox1. Granted Resa's suggestion for using Find with FirstOrDefault would be best to access one combobox.
List<ComboBox> ComboBoxes = groupBox1
.Controls
.OfType<ComboBox>()
.Select((control) => control).ToList();
foreach (var c in ComboBoxes)
{
Console.WriteLine(c.Name);
}
string nameOfComboBox = "comboBox1";
ComboBox findThis = groupBox1
.Controls
.OfType<ComboBox>()
.Select((control) => control)
.Where(control => control.Name == nameOfComboBox)
.FirstOrDefault();
if (findThis != null)
{
Console.WriteLine(findThis.Text);
}
else
{
Console.WriteLine("Not found");
}
You can use the ControlCollections Find Method, it has a parameter that will search the parent and its Children for your control.
ComboBox temp;
Control[] myControls = Controls.Find("myComboBox", true); //note the method returns an array of matches
if (myControls.Length > 0) //Check that it returned a match
temp = (ComboBox)myControls[0]; //use it

C# Selecting first row in CategorizedAlphabetical sorted ProperyGrid

I have ProperyGrid loaded with categorised PropertySpec and set to CategorizedAlphabetical sort. When form runs categories then items within categories are sorted. An annoying artefact is that PropertyGrid by default selects the first item after list was sorted and sometimes it scrolls view to selection. If item list is long you end up seeing list scrolled to somewhere in the middle.
Since PropertySpec can be created at runtime I want to always show the top of list on form load. PropertyGrid does not 'easily' expose collections and certainly not in ordered sequence. After googling around I am lead to believe this is not possible?
I came up with below code which proves otherwise.
Snippet will select fist category of sorted list. One could also select first item in that category expanding on the method but for my needs that was unnecessary.
// bind the PropertyTable to PropertyGrid
this.pg_Prefs.SelectedObject = proptable;
// get selected item
GridItem gi = this.pg_Prefs.SelectedGridItem;
// get category for selected item
GridItem pgi = gi.Parent.Parent;
//sort categories
List<GridItem> sortedCats = new List<GridItem>(pgi.GridItems.Cast<GridItem>());
sortedCats.Sort(delegate(GridItem gi1, GridItem gi2) { return gi1.Label.CompareTo(gi2.Label); });
// loop to first category
for (int i = 0; i < pgi.GridItems.Count; i++)
{
if (pgi.GridItems[i] == gi) break; // in case full circle done
// select if first category
if (pgi.GridItems[i].Label == sortedCats[0].Label)
{
pgi.GridItems[i].Select();
break;
}
}
Hope this will help others as well.
The simplified method of actually selecting category once you have sorted list would be to sortedCats[0].Select(); instead of looping through and checking each item. You would have to assert the list is not empty if you wanted to use that shortcut but that would gives some performance improvement...

Setting default item in combo box

I have a function for setting items in a combobox and one item is to be set by default like
--SELECT LIST--
public void SetOperationDropDown()
{
int? cbSelectedValue = null;
if(cmbOperations.Items.Count == 0)
{
//This is for adding four operations with value in operation dropdown
cmbOperations.Items.Insert(0, "PrimaryKeyTables");
cmbOperations.Items.Insert(1, "NonPrimaryKeyTables");
cmbOperations.Items.Insert(2, "ForeignKeyTables");
cmbOperations.Items.Insert(3, "NonForeignKeyTables");
cmbOperations.Items.Insert(4, "UPPERCASEDTables");
cmbOperations.Items.Insert(5, "lowercasedtables");
//ByDefault the selected text in the cmbOperations will be -SELECT OPERATIONS-.
cmbOperations.Text = "-SELECT OPERATIONS-";
}
else
{
if(!string.IsNullOrEmpty("cmbOperations.SelectedValue"))
{
cbSelectedValue = Convert.ToInt32(cmbOperations.SelectedValue);
}
}
//Load the combo box cmbOperations again
if(cbSelectedValue != null)
{
cmbOperations.SelectedValue = cbSelectedValue.ToString();
}
}
Can anyone suggest a way to do this?
I've rewritten this answer to clarify some stuff.
First, the "default" text must be added as combo item as well.
Usage of combo.Text property just adds descriptive text to combobox which is "lost" first time user do something with a control.
If you like to permanently have "default" text in your combo, you must add it as an combobox item.
By the code you provided, just modify the
cmbOperations.Text = "-SELECT OPERATIONS-"; to
cmbOperations.Items.Insert(0, "-SELECT OPERATIONS-");
Note that this way you add the item "-SELECT OPERANDS-" to the 0th (read first) position in the list.
Also make sure that all your following items are increased by 1, because they are now moved by one space down in list.
Finally, put cboOperations.SelectedIndex = 0; line at the end of code. By doing so, you're telling combobox to display your "default" item initially when the form (or control) loads.
One more thing. I'm not pretty sure what do you want to achieve with the code beyond setting combo items, but if you like to check what user selected use cboOperations.SelectedIndex property which contains currently selected item in combo. You can add simple if(cboOperations.SelectedIndex == someIntValue){...}
The rest is your program logic ;)

Categories