Do function on only 1 Control of NumericUpDown - c#

I let a supertooltip (from DotNetBar) appear on every control of NumericUpDown. But I only need a supertooltip on the TextBox of NumericUpDown. Here is my current code:
foreach (Control c in NumericUpDown.Controls)
{
NumericUpDownToolTip.SetSuperTooltip(c, NumericUpDownSuperToolTip);
}
//Declarations:
//NumericUpDownToolTip is a SuperToolTip from DotNetBar
//NumericUpDownSuperToolTip is the configuration of the SuperToolTip (for example: the text of the tooltip)
So how do I set the tooltip only on the textbox?

Modify your foreach to be this:
foreach (Control c in NumericUpDown.Controls.OfType<TextBox>())

You could do it the old fashioned way:
foreach (Control c in NumericUpDown.Controls)
{
if (!(c is TextBox)) continue;
NumericUpDownToolTip.SetSuperTooltip(c, NumericUpDownSuperToolTip);
}
Or use LINQ to accomplish the same
var controls = NumericUpDown.Controls.Where(c => c is TextBox);
foreach (Control c in controls)
NumericUpDownToolTip.SetSuperTooltip(c, NumericUpDownSuperToolTip);

Related

How to remove all controls except one?

If I want to remove all the GroupBox controls, I can use:
foreach (Control c in this.Controls.OfType<GroupBox>().ToList())
{
this.Controls.Remove(c);
}
How can I have an exception here? In other words, I would like to delete all the GroupBox controls except where the name of the GroupBox is "Groupbox1".
An alternative to Rufus's solution if you know the names of the GroupBoxes that you want to exclude beforehand, you can use the Enumerable.Except() method:
foreach (var grp in Controls.OfType<GroupBox>().
Except(new[] { groupBox1, groupBox7 }).ToList())
{
Controls.Remove(grp);
}
You can add a filter to your query to exclude the name of the control you don't want to delete:
foreach (var groupBoxToDelete in Controls.OfType<GroupBox>().ToList()
.Where(ctrl => ctrl.Name != "groupBox1"))
{
Controls.Remove(groupBoxToDelete);
}

How to exclude a particular kind of control from a foreach loop?

I am attempting to validate a forms controls to see if they are empty and found an interesting point in my flailing.
List<string> emptycontrols = new List<string>();
foreach (Control control in Mainform.V_Datafield.Controls)
{
if (control.Text.Contains(null))
{
emptycontrols.Add(control.Name);
}
}
if (emptycontrols.Count > 0)
{
MessageBox.Show("Empty fields detected:", emptycontrols.ToString());
}
Above is my mediocre solution and when run it comes up that a control, namely the DateTimePicker control can never be empty and quite rightly so.
Ultimately my question is how would I exclude the DateTimePicker control from the foreach loop so that it will ignore it but continue to check the other controls?
The groupbox (V_datafield) contains:
10 x TextBoxes
1 x RichTextBox
1 x DateTimePicker as mentioned above.
You can always check like following inside your foreach loop
if (control is DateTimePicker)
continue;
You could use is like this:
foreach (Control control in Mainform.V_Datafield.Controls)
if (!(control is DateTimePicker) && string.IsNullOrEmpty(control.Text))
emptycontrols.Add(control.Name);
Or, actually, your loop could be removed using LINQ to become:
var emptyControls = Mainform.V_Datafield.Controls
.Cast<Control>()
.Where(control => !(control is DateTimePicker))
.Where(control => string.IsNullOrEmpty(control.Text))
.Select(control => control.Name);
using two Where to keep the logic from the previous code but they could be merged using &&.

How can I read ListView Column Headers and their values?

I've been trying to find out a way to read data from the selected ListView row and display each value in their respected TextBox for easy editing.
The first and easiest way would be something like this:
ListViewItem item = listView1.SelectedItems[0];
buyCount_txtBox.Text = item.SubItems[1].Text;
buyPrice_txtBox.Text = item.SubItems[2].Text;
sellPrice_txtBox.Text = item.SubItems[3].Text;
There is nothing wrong with that code but I have around 40 or more TextBoxes that should display data. Coding all 40 or so would become very tedious.
The solution I've come up with, is to get all TextBox Controls in my User Control like so:
foreach (Control c in this.Controls)
{
foreach (Control childc in c.Controls)
{
if (childc is TextBox)
{
}
}
}
Then I need to loop the selected ListView row column headers. If their column header matches TextBox.Tag then display the column value in their respected TextBox.
The final code would look something like this:
foreach (Control c in this.Controls)
{
foreach (Control childc in c.Controls)
{
// Needs another loop for the selected ListView Row
if (childc is TextBox && ColumnHeader == childc.Tag)
{
// Display Values
}
}
}
So then my question would be: How can I loop through the selected ListView Row and each column header.
Looping over your ColumnHeaders is simply done like this:
foreach( ColumnHeader lvch in listView1.Columns)
{
if (lvch.Text == textBox.Tag) ; // either check on the header text..
if (lvch.Name == textBox.Tag) ; // or on its Name..
if (lvch.Tag == textBox.Tag) ; // or even on its Tag
}
However the way you loop over your TextBoxes is not exactly nice even if it works. I suggest that you add each of the participating TextBoxes into a List<TextBox>. Yes, that means to add 40 items, but you can use AddRange maybe like this:
To fill a list myBoxes:
List<TextBox> myBoxes = new List<TextBox>()
public Form1()
{
InitializeComponent();
//..
myBoxes.AddRange(new[] {textBox1, textBox2, textBox3});
}
Or, if you really want to avoid the AddRangeand also stay dynamic, you can also write a tiny recursion..:
private void CollectTBs(Control ctl, List<TextBox> myBoxes)
{
if (ctl is TextBox) myBoxes.Add(ctl as TextBox);
foreach (Control c in ctl.Controls) CollectTBs(c, myBoxes);
}
Now your final loop is slim and fast:
foreach( ColumnHeader lvch in listView1.Columns)
{
foreach (TextBox textBox in myBoxes)
if (lvch.Tag == textBox.Tag) // pick you comparison!
textBox.Text = lvch.Text;
}
Update: since you actually want the SubItem values the solution could look like this:
ListViewItem lvi = listView1.SelectedItems[0];
foreach (ListViewItem.ListViewSubItem lvsu in lvi.SubItems)
foreach (TextBox textBox in myBoxes)
if (lvsu.Tag == textBox.Tag) textBox.Text = lvsu.Text;
Try this one for greeting all the values.
foreach (ListViewItem lvi in listView.Items)
{
SaveFile.WriteLine(lvi.Text + "_" + lvi.SubItems[1].Text);
}

How to get a value from a hashtable entry

I have put all of my form controls in a hashtable thus :-
foreach (Control c in this.Controls)
{
myhash.Add(c.Name, c);
}
amongst which are two radio buttons. I would like to get the value of the buttons, ie checked or unchecked, and assign them to a variable. How can I do that please. Thanks for all and any help.
foreach (Control c in hashtable.Values)
{
if(c is RadioButton)
{
string name = x.Name;
bool isChecked = (c as RadioButton).Checked;
}
}
or if you know the name
(hashtable["name"] as RadioButton).Checked;
You can retrieve a value by a key associated with it, basically control Name is a key in hashtable you've created. So if you know a name of controls you need to access:
var control = hash[radioButtonControlName] as RadioButton;
Otherwise using LINQ OfType() and List.ForEach():
// OfType() does check whether each item in hash.Values is of RadioButton type
// and return only matchings
hash.Values.OfType<RadioButton>()
.ToList()
.ForEach(rb => { bool isChecked = rb.Checked } );
OR using foreach loop:
(there is a nice overview of misconception of the List.ForEach() usage)
var radioButtons = hash.Values.OfType<RadioButton>();
foreach(var button in radioButons)
{
bool isChecked = rb.Checked;
}
Cast the control that is the radio button to a RadioButton Class instance and then look at the checked property. At least that would be how I've done this many times over in WebForms using similar classes.
Assuming the hashtable in your code is an instance of Hashtable:
Hashtable myhash= new Hashtable();
foreach (Control c in this.Controls)
{
myhash.Add(c.Name, c);
}
You can do this:
foreach (DictionaryEntry entry in myhash)
{
RadioButton rb = entry.Value as RadioButton;
if (rb != null)
bool checked = rb.Checked;
}
Also you can see the key of the hashmap entry with:
foreach (DictionaryEntry entry in myhash)
{
var componentName = entry.Key;
}
That will correspond with the name of the component that you put in the hashmap (c.Name).
Hope this help you.

How do you access a Control in a collection by its Type?

How does one target a control by its Type?
I have a Control collection "TargetControls"
List<Control> TargetControls = new List<Control>();
foreach (Control page in Tabs.TabPages)
{
foreach (Control SubControl in page.Controls)
TargetControls.Add(SubControl);
}
foreach (Control ctrl in TargetControls)...
I need to access each existing control (combobox,checkbox,etc.) by its specific Type with access to its specific properties. The way I'm doing it now only gives me access to generic control properties.
Can't I specify something like...
Combobox current = new ComboBox["Name"]; /// Referencing an Instance of ComboBox 'Name'
and then be given access to it's (already existing) properties for manipulation?
You can use the is keyword to check for a specific type of the control. If the control is of a specific type, do a typecast.
foreach (Control SubControl in page.Controls)
{
if (SubControl is TextBox)
{
TextBox ctl = SubControl as TextBox;
}
}
You can use the OfType<T> extension method:
foreach (var textBox = page.Controls.OfType<TextBox>()) {
// ...
}
You'll need to cast the control to the right type of control before accessing any specific parameters.
ComboBox c = ctrl as ComboBox;
If (c != null)
{
//do some combo box specific stuff here
}
Also you could add the controls to a generic dictionary<string, control> and use the control.name as the key there.
Ex.
Dictionary<string, Control> TargetControls = new Dictionary<string, Control>();
Assuming you can use LINQ, and you're looking for (say) a Button control:
var button = (from Control c in TargetControls
where c.Name == "myName" && c is Button
select c
).FirstOrDefault();
...which will give you the first Button control named "myName" in your collection, or null if there are no such items present.
What about the Find method?
Button btn = (Button)this.Controls.Find("button1", true)[0];
btn.Text = "New Text";
In order to access a control's specific properties, you have to cast it to its appropriate type. For example, if the item in your TargetControls collection was a textbox, you would have to say ((TextBox)TargetControls[0]).Text = 'blah';
If you don't know the types ahead of time, you can use reflection to access the properties, but I'd need to have a better example of what you're trying to do first...

Categories