I have a menu structure already set up on a form and I want to programatically enable or disable certain menu items using a database.
I have got to the last stage where I have a class of AllowedMenu and CodeNames (which match the toolstripmenuitems exactly), and all I want to do it convert the CodeName into a ToolStripMenuItem from a String.
How could I do this?
Seem to have found something that works...
var m = menuStrip1.Items.Find(menuItem.CodeName, true);
var o = m.ToList();
foreach (var p in o)
{
p.Visible = false;
}
Thanks all..
You can access ToolStripItems throught Items property of the ToolStrip. If you have exactly name of the item (in CodeName variable), you could do something like this:
if (toolStrip1.Items.ContainsKey(CodeName)) //Just in case...
{
var yourItem = toolStrip1.Items[CodeName];
}
Related
I would like to select checkboxes
not by Design name but by parameters. More specifically, I would like to
check the checkboxes which has the parameters which are also in the data
retrieved from the database.
Example code :
(checkBox) C1.checked = true;
This is how I can set checked right now,
but I want to do something like...
string[] datas = db.getData();
foreach (string data in datas)
{
if (data.Equals("C1"))
{
C1.checked = true;
}
}
Of course I can do this for every checkboxes,
but there are over 50 checkboxes and I think it's stupid
to manually checking this but I couldn't find a way to select a particular checkbox based on the name.
Also, it would be really helpful if someone knows a way to group the textboxes,
so that I don't have to loop over every checkboxes every time. By that, I mean something like contains method within a group of checkboxes to find particular one.
It seems like your main goal is to find:
a way to group the textboxes, so that I don't have to loop over every
checkboxes every time.
You can create a Dictionary of string/Checkbox and select the checkbox that way.
Something like:
string key = "C1";
Dictionary<string, CheckBox> pairs = new Dictionary<string, CheckBox>();
pairs[key].Checked = true;
You Can do like below Using FindControl :
string[] datas = db.getData();
foreach (string data in datas)
{
CheckBox chk = this.Controls.Find(data, true).FirstOrDefault() as CheckBox;
if(chk !=null)
chk.Checked = true;
}
I currently have 100+ labels, with names like:
labelNumber1
labelNumber2
labelNumber3
labelNumber4
....
labelLetter1
labelLetter2
labelLetter3
labelLetter4
....
How would I find all the labels that have "Number" in the controls name?
Instead of having to type out labelNumber1.text = "hello", etc.
I have tried regex and foreach with wild cards but did not succeed.
I have looked on msdn.microsoft.com about using regex with a control.
You can loop through the Controls collection of the form and just check the name of each control that it contains something like 'Label'. or you could check that the control is a typeof TextBox, Label, etc.
E.g.
foreach (Control control in form.Controls)
{
if (control.Name.ToUpper().Contains("[Your control search string here]"))
{
// Do something here.
}
if (control is TextBox) {
// Do something here.
}
}
you can filter the list of controls to only return the labels. You would also want to make sure the name is greater than 11 chars.
List<Label> allNumberLabels = new List<Label>();
foreach (Label t in this.Controls.OfType<Label>())
{
if (t.Name.Length > 11)
{
if (t.Name.Substring(5, 6).Equals("Number"))
{
allNumberLabels.Add(t);
}
}
}
I know this is an old question, but I am here now, and:
The question asks about searching for multiple controls. This solution actually applies to any type of control.
OP was conflicted between using "Contains" or regex. I vote for regex! string.Contains is a bad idea for this kind of filter, since "CoolButton" has a "Button" in it too"
Anyway, here is the code:
public List<TControlType> FindByPattern<TControlType>(string regexPattern)
where TControlType:Control
{
return Controls.OfType<TControlType>()
.Where(control => Regex.IsMatch(control.Name, regexPattern))
.ToList();
}
Usage:
//some regex samples you can test out
var startsWithLabel = $"^Label"; //Matches like .StartsWith()
var containsLabel = "Label"; //Matches like .Contains()
var startsWithLabelEndsWithNumber = "^Label.*\\d+&"; //matches Label8sdf12 and Label8
var containsLabelEndsWithNumber = "Label.*\\d+&"; //matches MyLabelRocks83475, MyLabel8Rocks54389, MyLabel8, Label8
var hasAnyNumber= "^CoolLabel\\d+$"; //matches CoolLabel437627
var labels = FindByPattern<Label>("^MyCoolLabel.*\\d+&");
var buttons = FindByPattern<Button("^AveragelyCoolButton.*\\d+&");
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
This problem seems simple enough. I have a treeview, let's call it MyTreeView, populated with all of the drive letters, so the treeview looks like this:
A:\
C:\
D:\
F:\
How do I check if the treeview contains a specific item? How does the treeview identify its items?
I have created a MessageBox to show MyTreeView.Items.GetItemAt(1), and it identifies item 1 as:
"System.Windows.Controls.TreeViewItem Header:C:\ Items.Count:1"
Try the easiest thing first, which obviously doesn't work:
if (MyTreeView.Items.Contains(#"C:\")
{
MessageBox.Show(#"Tree contains C:\");
}
The next easiest thing would be to try making a TreeViewItem that looks similar to what I want, which also doesn't work:
TreeViewItem myItem = new TreeViewItem();
myItem.Header = #"C:\";
if (MyTreeView.Items.Contains(myItem)
{
MessageBox.Show("Tree contains " + myItem.ToString());
}
Just to make sure I had the fundamental concept right, I tried some circular logic, which actually does work:
var myItem = MyTreeView.Items.GetItemAt(1);
if (MyTreeView.Items.Contains(myItem)
{
MessageBox.Show("Tree contains " + myItem.ToString());
}
Which outputs:
"Tree contains System.Windows.Controls.TreeViewItem Header:C:\ Items.Count:1"
What am I doing wrong? How do I check if my tree contains something like "C:\" ?
edit:
The code for building the tree is this:
(basically a copy and paste from the internet)
foreach (string myString in Directory.GetLogicalDrives())
{
TreeViewItem item = new TreeViewItem();
item.Header = myString;
item.Tag = myString;
item.FontWeight = FontWeights.Normal;
item.Items.Add(dummyNode); // this is (object)dummyNode = null
item.Expanded += new RoutedEventHandler(DWGFolder_Expanded);
item.Selected += new RoutedEventHandler(DWGFolder_Selected);
// the Expanded event is very similar,
// subitem.Header is the folder name (Testing),
// while subitem.Tag is the full path (C:\Testing)
MyTreeView.Items.Add(item);
}
So basically I'm trying to match TreeViewItem objects.
I believe .Contains() would check for the value by reference since it isn't a simple string object. This requires you to iterate through each of the items until you retrieve the item which matches the header.
LINQ Example
if (MyTreeView.Items.Cast<TreeViewItem>().Any(item => item.Header.ToString() == #"C:\"))
{
MessageBox.Show(#"Tree contains C:\");
}
Contains looks for the exact same instance inside the collection. If you don't have the object you want to check already, you can't use Contains.
But you can use some basic LINQ query... Add the LINQ namespace to your class:
using System.Linq;
If your items are indeed just Strings, then use this query (EDIT - Though, in case they're just Strings, Contains should work, since their equality comparers don't behave like those of regular reference types, but compare by value):
if (MyTreeView.Items.Cast<string>().Any(s => s == #"C:\"))
{
// Do stuff
}
If your items are TreeViewItems, you can use this one:
if (MyTreeView.Items.Cast<TreeViewItem>().Any(i => i.Header.ToString() == #"C:\"))
{
// Do stuff
}
But your items could be any class we don't know, or your header binding could change... Without knowing how you're adding the items to the TreeView, it's hard to give you the best alternative.
EDIT - Keep in mind that this will only search in the first level of the tree. If the item you're looking for is placed somewhere deeper, you'll have to do a recursive search. At that point, maybe just keeping the values stored somewhere from the start would be better.
The problem is faced under c# .NET, Visual Studio, Windows Form Application
I have a bunch of checkboxes placed randomly in one form and in one panel.
So, If any checkbox is selected in the form its value is supposed to be added up.
Bottomline: Instead of using plenty of "If-else loops", to evaluate whether its been checked or not. I wanna simplify it using a "for loop ".
Is there any Checkbox group name type feature, which I can use???
I wanna code something like this:
for(int i=0;i<checkboxes.length;i++)
{
string str;
if(chkbox.checked)
{
str+=chkbox.value;
}
}
Where checkboxes is a group name.
You can use a simple LINQ query
var checked_boxes = yourControl.Controls.OfType<CheckBox>().Where(c => c.Checked);
where yourControl is the control containing your checkboxes.
checked_boxes is now an object which implements IEnumerable<CheckBox> that represents the query. Usually you want to iterate over this query with an foreach loop:
foreach(CheckBox cbx in checked_boxes)
{
}
You also can convert this query to a list (List<Checkbox>) by calling .ToList(), either on checked_boxes or directly after the Where(...).
Since you want to concatenate the Text of the checkboxes to a single string, you could use String.Join.
var checked_texts = yourControl.Controls.OfType<CheckBox>()
.Where(c => c.Checked)
.OrderBy(c => c.Text)
.Select(c => c.Text);
var allCheckedAsString = String.Join("", checked_texts);
I also added an OrderBy clause to ensure the checkboxes are sorted by their Text.
CheckBox[] box = new CheckBox[4];
box[0] = checkBox1;
box[1] = checkBox2;
box[2] = checkBox3;
box[3] = checkBox4;
for(int i=0; i<box.length; i++)
{
string str;
if(box[i].checked== true)
{
str += i.value;
}
}
I think this code will work with DotNet4.0. Plz let me know any error occurs. Treat 'box' as regular array.
If all the checkboxes are in a groupbox you can do this:
foreach(Control c in myGroupBox.Controls)
{
if (c is CheckBox)
{
//do something
CheckBox temp = (CheckBox)c;
if(temp.Checked)
//its checked
}
}
Subscribe all checkboxes to one CheckedChanged event handler and build your string when any checkbox checked or unchecked. Following query will build string, containing names of all Form's checked checkboxes:
private void Checkbox_CheckedChanged(object sender, EventArgs e)
{
// this will use all checkboxes on Form
string str = Controls.OfType<CheckBox>()
.Where(ch => ch.Checked)
.Aggregate(new StringBuilder(),
(sb, ch) => sb.Append(ch.Name),
sb => sb.ToString());
// use string
}
I suppose other than subscribing to event CheckedChanged there is no alternative even if it is contained in some panel or form, You have to use if else,
if it would have been web base eg asp.net or php we could use jquery because it gives us the option to loop through each particular event using .each and getting its value