I have a series of of tabs that hold text boxes in them. Some of the tabs have a control that contains Text Boxes inside of a Scrollview as well. I am trying to iterate through the tabs and clear the content of the text boxes.
I was going to use this:
foreach(TabItem item in Tabs.Items)
{
ClearTextBoxes(this);
}
I then use this to clear to the text boxes:
TextBox tb = obj as TextBox;
if (tb != null)
tb.Text = "";
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
ClearTextBoxes(VisualTreeHelper.GetChild(obj, i));
}
It is currently only clearing the first tab and none of the rest.
Any ideas?
Use the LogicalTreeHelper. Only the items of the currently active tab are contained in the visual tree, therefore the visual tree helper is not the best choice for your task.
Iterating over the tab items is IMO not necessary, only if you have a lot of other controls not residing in the tab-items and therefore want to spare cpu power. As already mentioned by Bela R, there is an error in your call to ClearTextBoxes().
I think it should be ClearTextBoxes(item) and not ClearTextBoxes(this)
foreach(TabItem item in Tabs.Items)
{
ClearTextBoxes(item);
}
Related
I have a list of checkbox controls
public List<CheckBox> _checkBoxes = new List<CheckBox>();
I add a certain amount during runtime using a switch case with the properties such as location and visibility.
This all works fine, but if I want the checkboxes to disappear or become checked at some point the GUI doesn't get updated, the list is updated with the new data but just not visually.
* I ended up doing this*
I created a bunch of checkboxes on the winfrom.Created a method which you can choose which ones are visible. Then created a method to fill a list of type checkbox. Then you can search the panel for control types, once you found the control, it can be manipulated. This isn't elegant and probably isn't the best way, but i am new to custom controls and winforms.
//search panel for checkboxes
foreach (Control c in panel1.Controls)
{
if (c is CustomControls.RoundedCheckBox)
{
CustomControls.RoundedCheckBox checkBox = c as CustomControls.RoundedCheckBox;
//if it is checked add to list
if(checkBox.Checked)
{
_checkBoxes.Add(checkBox);
}
}
}
If you have something like this:
_checkBoxes.Add(new CheckBox());
_checkBoxes[0].Parent = this;
then you should be able to manipulate your checkboxes from the list:
_checkBoxes[0].Checked = false;
But, the problem may occur if you do it in some kind of loop and want to see the results immediately.
In Windows there is something called message loop. Application simply works like that (pseudocode: TL;DR)
while(true)
{
message = GetFirstMessage();
if(message != null)
{
if(message.Id == CloseApplication)
break;
DispatchMessage(message);
RemoveFirstMessage();
}
}
So, application takes message from queue, then process it. A message is everything - button click, mouse move, paint... Everything.
So when a message is dispatched it looks for the control that should receive this message and then it does some work.
So, for example if you have something like that:
foreach(var ch in _checkBoxes)
{
ch.Checked = false;
DoSomeWorkThatTakesTime();
ch.Checked = true;
}
You won't see the change, because you are "trapped" in DispatchMessage. When you set Checked, you really sending a message. But this message cannot be Dispatched right now, because you are inside the foreach loop.
So the only thing you can do here is to tell your application - now, please DO READ message queue. In WinForms it's called "DoEvents", so this will do the work:
foreach(var ch in _checkBoxes)
{
ch.Checked = false;
Application.DoEvents();
DoSomeWorkThatTakesTime();
ch.Checked = true;
Application.DoEvents();
}
I need this page to be very easily maintained, so I need most of the stuff to be programmatically generated. I need to create checkboxes next to normal Labels, without touching the .aspx file. right now I generate a list with all labels on my page called labels. Each label on my site has an ID beginning with lbl_, but the ones that are supposed to have a checkbox begin with lblx_. I then want to use something like this to create said checkboxes:
foreach (Label label in labels)
{
if (label.ID.Contains("lblx_"))
{
CheckBox cb = new CheckBox();
cb.ID = "cb_statistikname_" + label.ID;
label.Controls.AddAt(0, cb);
}
}
Right now this code replaces the labels, the same happens when I use label.Control.Add(cb)
You can use Page.Controls.AddAt() with combination of page.Page.Controls.IndexOf()
if(label.Parent != null && label.Parent.Controls.IndexOf(label) >= 0)
label.Parent.Controls.AddAt(label.Parent.Controls.IndexOf(label) + 1, cb);
Note :This should be done in Page PreInit events.
If you set the Text property in your Label control, basically all child controls get wiped out. See this answer: asp:label doesn't render children
I'm trying to load a form with different information depending on which component of my listbox I double click. If I get which box was clicked(box 1, box2, etc.), that would be enough.
I've tried using the Doubleclick event, but it returns an object, and I'm not quite sure what to do with this object to get what I need.
Heres my code right now:
for (int i = 0; i <= (Program.Customers.Count) - 1; i++)
{
if (Program.Customers[i].Name == searchTerm)
{
SearchIndex.Add(i);
listBox1.Items.Add(((Program.Customers[i].ID + " - " + Program.Customers[i].Name)));
}
}
listBox1.Show();
What would be the best way to get which box was clicked? I need the ID, but I can get that with box was clicked.
Thanks!
In the simplest case, you can directly compare the sender argument with your ListBox control instances, for example:
if (sender == listBox1)
{
// ...
}
To get more information out of sender you need to cast it to something more specific first. So if you know your double click handler was only attached to list boxes, you can do
var listbox = (ListBox)sender;
and then access any of the properties of ListBox (such as Tag, which I mention because it's there specifically for your custom needs).
I'm currently working on a small side project as a way of getting used to Forms in Visual Studio 2012, as I usually only work with Console Applications. My current layout is designed to use tabs, and the user is to specify how many of the tabs they need for this application. They then fill out some information and it will be formatted and output to a file at a location specified by the user. On to the questions.
In order to stop duplicate tabs from existing, I'm using the following:
private void comboTabs_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboSkills.SelectedIndex == 0)
{
tabControl1.TabPages.Remove(tab8);
tabControl1.TabPages.Remove(tab7);
tabControl1.TabPages.Remove(tab6);
tabControl1.TabPages.Remove(tab5);
tabControl1.TabPages.Remove(tab4);
}
//repeat for Index 1, 2 and so on
}
There will always be a minimum of 3 tabs, so the first selection on the combo box removes tabs 4 through 8. The next selection does the same, but then adds tab4 back again. This goes on for the following selections. Is there any way I can do this more conveniently?
Second question, each tab has a series of text boxes and combo boxes that users are to select information from. The problem I'm having is that I need to identify how many tabs the user has selected and then only pull information from those tabs. I'm aware that I can get the number of tabs with:
int numberoftabs = tabControl1.TabCount;
But after that I can't seem to read the information from them. I'm intending to do
for (int i = 0; i < numberoftabs; i++)
{
//get textbox text of tab i and so on
}
Is there any way I can do this? I was hoping to use a tab layout since I like my current layout very much. If it makes a difference, all the tabs have the same layout, and share a naming convention such as tab 1 text box 1 is textTab1Name, tab 2 text box 2 is textTab2Name and so on.
For the first part of your question, you can handle all cases with this piece of code:
var tabCount = 5 - comboBox1.SelectedIndex;
for (var i = 0; i < tabCount; i++)
{
tabControl1.TabPages.RemoveAt(7-i);
}
For the second part you will have to create this method:
private T GetControl<T>(string name) where T : Control
{
return (T) this.Controls.Find(name, true).FirstOrDefault();
}
Then you can write your text retrieval loop like this:
for (int i = 0; i < numberoftabs; i++)
{
//get textbox text of tab i and so on
TextBox textBox1 = GetControl<TextBox>("textTab" + i + "Name");
...
etc..
}
Is there a straighforward way to set additional text to appear in a tooltip when a user's mouse is held over an item in a CheckedListBox?
What I would expect to be able to do in code is:
uiChkLstTables.DisplayOnHoverMember = "DisplayOnHoverProperty"; //Property contains extended details
Can anyone point me in the right direction to do this? I've already found a couple of articles that involve detecting which item the mouse is currently over and creating a new tooltip instance, but this sounds a little too contrived to be the best way.
Thanks in advance.
Add a Tooltip object to your form and then add an event handler for the CheckedListBox.MouseHover that calls a method ShowToolTip();
Add MouseMove event of your CheckedListBox which has the following code:
//Make ttIndex a global integer variable to store index of item currently showing tooltip.
//Check if current location is different from item having tooltip, if so call method
if (ttIndex != checkedListBox1.IndexFromPoint(e.Location))
ShowToolTip();
Then create the ShowToolTip method:
private void ShowToolTip()
{
ttIndex = checkedListBox1.IndexFromPoint(checkedListBox1.PointToClient(MousePosition));
if (ttIndex > -1)
{
Point p = PointToClient(MousePosition);
toolTip1.ToolTipTitle = "Tooltip Title";
toolTip1.SetToolTip(checkedListBox1, checkedListBox1.Items[ttIndex].ToString());
}
}
Alternately, you could use a ListView with checkboxes instead. This control has
builtin support for tooltips.
Contrived or not; that's what there is...
I'm not aware of an easier way than you have already described (although I'd probably re-use a tooltip instance, rather than creating new all the time). If you have articles that show this, then use them - or use a 3rd party control that supports this natively (none leap to mind).
I would like to expand upon Fermin's answer in order to perhaps make his wonderful solution slightly more clear.
In the form that you're working in (likely in the .Designer.cs file), you need to add a MouseMove event handler to your CheckedListBox (Fermin originally suggested a MouseHover event handler, but this did not work for me).
this.checkedListBox.MouseMove += new System.Windows.Forms.MouseEventHandler(this.showCheckBoxToolTip);
Next, add two class attributes to your form, a ToolTip object and an integer to keep track of the last checkbox whose tool tip was shown
private ToolTip toolTip1;
private int toolTipIndex;
Finally, you need to implement the showCheckBoxToolTip() method. This method is very similar to Fermin's answer, except that I combined the event callback method with the ShowToolTip() method. Also, notice that one of the method parameters is a MouseEventArgs. This is because the MouseMove attribute requires a MouseEventHandler, which then supplies MouseEventArgs.
private void showCheckBoxToolTip(object sender, MouseEventArgs e)
{
if (toolTipIndex != this.checkedListBox.IndexFromPoint(e.Location))
{
toolTipIndex = checkedListBox.IndexFromPoint(checkedListBox.PointToClient(MousePosition));
if (toolTipIndex > -1)
{
toolTip1.SetToolTip(checkedListBox, checkedListBox.Items[toolTipIndex].ToString());
}
}
}
Run through your ListItems in your checkbox list of items and set the appropriate text as the item 'title' attribute, and it will display on hover...
foreach (ListItem item in checkBoxList.Items)
{
//Find your item here...maybe a switch statement or
//a bunch of if()'s
if(item.Value.ToString() == "item 1")
{
item.Attributes["title"] = "This tooltip will display when I hover over item 1 now, thats it!!!";
}
if(item.Value.ToString() == "item 2")
{
item.Attributes["title"] = "This tooltip will display when I hover over item 2 now, thats it!!!";
}
}