I'm cycling over my WinForms controls and give their Text and ToolTipText to my Translation service for translation.
Example:
foreach (ToolStripItem item in toolStrip.Items)
{
if (item is ToolStripMenuItem)
{
item.ToolTipText = Translate(item.ToolTipText);
item.Text = Translate(item.Text);
}
}
However, I cannot access tooltips set by using the WinForms ToolTip control.
I see I can cycle over the components. Can I Get and Set their tooltips?
protected void TranslateToolTip(ToolTip toolTip)
{
foreach (var component in toolTip.Container.Components)
{
// Doesn't work. No ToolTipText property
component.ToolTipText = Translate(component.ToolTipText);
}
}
Can I access the tooltip text directly from the control?
To set a tooltip text on all components in your form like button1 etc. I think you should use something like this:
foreach (var control in this.Controls) {
ToolTip1.SetToolTip(this.control, "Your text");
}
That's because ToolTip doesn't have a Text property and it's set like on example above.
See also ToolTip Class and ToolTip.SetToolTip Method and ToolTip.GetToolTip Method
Or you can try something like that but not sure if this gonna work:
protected void TranslateToolTip(ToolTip toolTip)
{
foreach (var component in toolTip.Container.Components)
{
// Doesn't work. No ToolTipText property
// component.ToolTipText = Translate(component.ToolTipText);
toolTip.SetToolTip(component , (string)Translate(toolTip.GetToolTip(component));
}
}
I don't know what Translate(component.ToolTipText) is supposed to return. If it's just translated string, then we don't need the (string) part in my exmple.
Hope it helps.
EDIT: Fixed second example to show how to Set and Get tooltip text from specific control.
Related
I have tons of Buttons named like this x0y1
How do I access the variable name dynamically so I could loop all names by xiy1 or so.
in PHP it would be like ${"myString" . $randomvar}
I can't use a list or array because the the button already exist defined through the xaml
You can use:
var textbox =
this.Controls.OfType<TextBox>().Where(txb => txb.Name == "myString").FirstOrDefault();
This assumes you are in the context of your form (this.Controls).
And of course, don't forget to add using System.Linq;...
You can get all the textbox using this method
void AllTextBox(System.Windows.Forms.Control.ControlCollection ctrls)
{
foreach (Control ctrl in ctrls)
{
if (ctrl is TextBox)
{
if (ctrl.Name == "textBox1")
{
// do your stuf with textbox
}
}
}
}
You can create function that return control by name :
Control GetControlByName(string Name)
{
foreach(Control control in this.Controls)
if(c.Name == Name) return control ;
return null;
}
or Function with a specific control like that :
Button GetButtonByName(string Name)
{
foreach (Control c in this.Controls.OfType<Button>())
if (c.Name == Name) return c;
return null;
}
For wpf project...
Let's say you have a grid named MyGrid and there's lot of buttons on it.
You want to refer to the button named x0y1:
var btn = MyGrid.Children.OfType<Button>().Where(x=>x.Name=="x0y1");
Note: above code should work for flat structure (one level deep only).
You can achieve the same by using code provided in this thread: How can I find WPF controls by name or type?
Just call FindName("elementName"). FindName searches through all child elements of a FrameworkElement. To access any button by its name as string in a window, call the FindName() method of the window !
If your code is in a class inheriting from Window, just use:
Button button = (Button)FindName("xiy1");
If you write the code in a class not inheriting from Window but FrameworkElement, which is unlikely, use:
Window window = Window.GetWindow(this);
Button button = (Button)window.FindName("xiy1");
Check the MSDN documentation about Namescopes for more information about limitations.
I'm looping through the Controls collection of an asp:Panel, and I am not sure how to set Properties specific to some controls...
For example the Panel might contain a DropDownList, and I would like to be able to set and get the SelectedValue of this. Or it might contain a TextBox, and I would like to set and get the Text property.
I'm using this code to traverse:
foreach (Control control in panel.Controls)
{
// ...
}
And since I get just a Base Control from this, it appears not to be able to get/set any of these properties as they are not defined for the Base Control.
So, what to do?
Thanks
One possibility is to use the as operator:
foreach (Control control in Controls) {
TextBox txt = control as TextBox;
if (txt!=null) {
txt.Text = "bla";
...
}
ComboBox cbo = control as ComboBox;
if (cbo!=null) {
cbo.SelectedItem = ...
...
}
...
}
Note: If you have multiple controls of one type, you may use the Tag property to store additional information. While Tag is of type object, you also need the as operator here...
You could always check the type, and then cast it to that type.
foreach (Control control in Controls)
{
if (control.GetType().Equals(typeof(DropDownList)))
{
((DropDownList)control).Enabled = value;
}
}
You should be able to use the is operator like so:
if(control is DropDownList)
{
// Cast control as DDL and do your work
}
The ListView seems to be as cantankerous as a polecat and as temperamental as a [elided by the P.C. police]
With help from - and others, I was able to get a ListView working just as I wanted
it to
(http://stackoverflow.com/questions/11423537/how-to-add-subitems-to-a-listview).
Now I'm converting that simple demo for use in a real app.
I create the columns in the form's Load event:
listViewGroupsItems.Columns.Add(colHeadName);
listViewGroupsItems.Columns.Add(colHeadRate);
...but they don't display. However, there is a blank line above my first item. So why are no text values being displayed. Are they "there" but invisible? Why would they get wiped out?
Anyway, what I want to see is:
column1Title column2Title
Group1Name
Item subitem
Item subitem
Group2Name
Item subitem
Group1Name
Item subitem
Item subitem
Item subitem
Item subitem
...but what I actually see is just:
[blank line]
Group1Name
...that's it!
The ListView's View property is set to Details; otherwise, all of the properties are the default values.
My listview code is:
private void AddGroupsAndItems() {
Dictionary<string, string> GroupsDict = PlatypusData.GetGroupsForTopLevel(Convert.ToInt32(labelTopLevel.Tag));
int currentGroup = 0;
foreach (KeyValuePair<string, string> entry in GroupsDict) {
string GroupNumber = entry.Key;
string GroupName = entry.Value;
listViewGroupsItems.Groups.Add(new ListViewGroup(GroupName, HorizontalAlignment.Left));
Dictionary<string, string> ItemsDict = PlatypusData.GetItemsForGroup(GroupNumber);
foreach (KeyValuePair<string, string> itemEntry in ItemsDict) {
string itemID = itemEntry.Key;
string itemName = itemEntry.Value;
ListViewItem lvi = new ListViewItem(string.Format("{0} ({1})", itemName, itemID));
lvi.SubItems.Add(PlatypusData.GetDuckbillNameForItemId(itemID));
listViewGroupsItems.Items.Add(lvi);
listViewGroupsItems.Groups[currentGroup].Items.Add(lvi);
}
currentGroup++;
}
}
UPDATE
I changed my code in the form's Load event from:
var colHeadName = new ColumnHeader { Text = Resources.RateRequestForm_RateRequestForm_Load_Billing_Account_Client, Width = 160 };
var colHeadRate = new ColumnHeader { Text = Resources.RateRequestForm_RateRequestForm_Load_RatePlan_ID, Width = 120 };
listViewCustomerBillAccountsClients.Columns.Add(colheadName); //colHeadName);
listViewCustomerBillAccountsClients.Columns.Add(colheadRate); //colHeadRate);
...to:
ColumnHeader colheadName = new ColumnHeader();
ColumnHeader colheadRate = new ColumnHeader();
listViewCustomerBillAccountsClients.Columns.Add(colheadName);
listViewCustomerBillAccountsClients.Columns.Add(colheadRate);
...and it made no difference at all.
It would seem that the ColumnHeader constructor should be able to take a string of what it should display, but even when I do that:
ColumnHeader colheadName = new ColumnHeader("This");
ColumnHeader colheadRate = new ColumnHeader("That");
...there is still no change (according to Intellisense or whatever it's called, the string arg is an ImageKey, but I thought I'd try just out of thoroughness/frustration.
Late to the party, but I've just spent some time trying to solve a similar problem. The answer I found was that when clearing the list before filling, you must use
listviewGroupItems.Items.Clear();
not
listviewGroupItems.Clear();
The ListView.Clear() method clears everything from the control--including the columns
I had the same issue today. I had coded listView.Clear() as user2867342 mentioned. I needed to change that to listView.Items.Clear(), but that did not make the columns appear. The columns were there, and I could click on them and resize them, but they were completely blank.
I had a ListView set to Details mode. I also had set the OwnerDraw property to true, because I wanted to paint my own progress bar column. MSDN says the following about the OwnerDraw property (emphasis mine):
A ListView control is normally drawn by the operating system. In order
to customize the appearance of ListView items, subitems, and column
headers, set the OwnerDraw property to true and provide a handler for
one or more of the following events: DrawItem, DrawSubItem,
DrawColumnHeader. This is called owner drawing. When the View property
is set to View.Details, all three events occur; otherwise, only the
DrawItem event occurs.
I had to implement the DrawColumnHeader event. In my case, the defualt worked fine, so the method sets the DrawDefault event parameter to true. After implementing this event handler, the column headers appeared correctly:
...Windows.Forms designer code...
listView.DrawColumnHeader += new DrawListViewColumnHeaderEventHandler(this.listView_DrawColumnHeader);
...
private void listView_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
e.DrawDefault = true;
}
You're missing column headers in your code. (fixed)
Per the MSDN:
"If your ListView control does not have any column headers specified and you set the View property to View.Details, the ListView control will not display any items. If your ListView control does not have any column headers specified and you set the View property to View.Tile, the ListView control will not display any subitems."
Granted, you'll probably need to make more adjustments than what you see in my SS, but it at least answers your question as to why you are getting blanks.
Edit (Changed lines, although changing them back to your code didn't skew my successful results):
lvi.Group = listViewGroupsItems.Groups[currentGroup];
listViewGroupsItems.Items.Add(lvi);
One more thing to check I just found:
OwnerDraw must be false.
Copy & Paste from previous project and forgot that I used OwnerDraw
I have many buttons and labels on my c# form. I have a button that changes all butons' and labels' text properties (change language button). Do i have to write all items in click event of button or is there a method that scans all form control items and change their text properties.
There are many other controls that contains labels or buttons. For example a label is added to the control of a panel and when i iterate form controls, i can't reach this label. I want to change all items' text properties at one time.
Thank you.
foreach (Control objCtrl in yourFormName.Controls) {
if (objCtrl is Label)
{
// Assign Some Text
}
if (objCtrl is Button)
{
// Assign some text
}
}
If a CS0120 error happens, change yourFormName.Controls to this.Controls;
Assuming ASP.NET's ITextControl Interface (works similar for Winforms-Controls' Text-Property ):
var text = "Hello World";
var allTextControls = this.Controls.OfType<ITextControl>();
foreach(ITextControl txt in allTextControls)
txt.Text = text;
http://msdn.microsoft.com/en-us/library/bb360913.aspx
Edit: You could easily make it an extension(e.g. ASP.NET, for Winforms replace ITextControl with Control):
public static class ControlExtensions
{
public static void SetControlChildText(this Control rootControl, String text, bool recursive)
{
var allChildTextControls = rootControl.Controls.OfType<ITextControl>();
foreach (ITextControl txt in allChildTextControls)
txt.Text = text;
if (recursive) {
foreach (Control child in rootControl.Controls)
child.SetControlChildText(text, true);
}
}
}
Now you can call it for example in this way:
protected void Page_Load(object sender, EventArgs e)
{
Page.SetControlChildText("Hello World", true);
}
This will apply the given text on every child control implementing ITextControl(like Label or TextBox).
If it's winforms you should read about localizing your application here:
Walkthrough: Localizing Windows Forms
I think if you are using javascript, you can simply go through the DOM and modify the texts of the buttons and labels. Using jQuery this will be very simple
For a web application, you could do this quite easily with jQuery. Have a look at this: http://api.jquery.com/category/selectors/
$('label').each(function(){this.value = 'something else';});
For Winforms, you can use this:
foreach (var c in Controls.OfType<TextBox>())
c.Text = "TextBox Text";
foreach (var c in Controls.OfType<Label>())
c.Text = "Label text";
But I agree with #ionden, you should consider localizing your application.
There is a Controls property that contains all controls of your form. You can iterate over it:
foreach(var control in Controls)
{
var button = control as Button;
if(button != null)
button.Text = Translate(button.Text);
else
{
var label = control as Label;
if(label != null)
label .Text = Translate(label .Text);
}
}
foreach( Control ctlparent in this.Controls)
{
if(ctlparent is Panel or ctlparent is GroupBox)
{
foreach(Control ctl in ctlparent.Controls)
{
if(ctl is Label or ctl is Button)
{
ctl.Text= newtext;
}
}}
This will work.
Guys, I have a windows form with a panel control and inside the panel control are several other controls with a System.Windows.Forms.Tooltip attached to them. How can I iterate through each tooltip and set the Active property of the tooltip to false? Tooltips, unlike other controls, are not actually controls. So I had this:
foreach (System.Windows.Forms.Control ctrl in this.pnlControl.Controls)
{
if (ctrl.Name.StartsWith("tt")) // since all my tooltip names start with 'tt'
{
System.Windows.Forms.ToolTip TipControl=(System.Windows.Forms.ToolTip)ctrl;
TipControl.Active=false;
}
}
This does not work though. It gets an error because the ToolTip control is not inherited from System.Windows.Forms.Control. Any ideas?
EDIT:
Okay Guys. I probably didn't go into enough detail to get the answer I needed. My problem is, I'm taking all the controls in my panel and moving them to a different panel. Once they are switched over, the tooltips are still attached to the controls, which is what I want. However I have no way to deactive or reactivate them once I move them since the form and the original panel no longer exist. However, I found a solution which I will post here.
How to add tool tips for two buttons? The correct way is NOT creating two instances of ToolTip in this way:
ToolTip tt1 = new ToolTip(); //or you can create one in the designer
tt1.ToolTipTitle = "test";
tt1.SetToolTip(button1, "caption1");
ToolTip tt2 = new ToolTip();
tt2.ToolTipTitle = "test2";
tt2.SetToolTip(button2, "caption2");
Remember that a ToolTip instance and a control are not one-on-one related. The right way for this example is:
ToolTip tt1 = new ToolTip(); //or you can create one in the designer
tt1.ToolTipTitle = "test";
tt1.SetToolTip(button1, "caption1");
tt1.SetToolTip(button2, "caption2");
To remove the tooltip of button2, use:
tt1.SetToolTip(button2,string.Empty);
For your case,we can use
foreach(Control c in this.Controls)
{
tt.SetToolTip(c,string.Empty);
}
Typically, you have a single ToolTip instance that handles the displaying of tool tips for all of your controls. That single ToolTip instance is just a regular member of your form. Simply set it's Active property to false.
Edit: OK, scrap my previous answer. Yes, ToolTip is a Component, not a Control, so it's not actually in the Panel at all. From your question, it sounds like you have one ToolTip instance and you use it for controls inside this Panel as well as for other controls, right? In that case the solution is simple: create a separate ToolTip instance and use that one for controls in the Panel, then just refer to it directly to deactivate it, eg.
ttPanel.Active = false;
Okay what I did was create a new class that is inherited from Control, like so:
public class TooltipMaster : System.Windows.Forms.Control
{
private System.Windows.Forms.ToolTip m_tooltip1;
private System.Windows.Forms.ToolTip m_tooltip2;
private System.Windows.Forms.ToolTip m_tooltip3;
private System.Windows.Forms.ToolTip m_tooltip4;
public System.Windows.Forms.ToolTip ToolTip1 {
get { return m_tooltip1; }
set { m_tooltip1 = value; }
}
public System.Windows.Forms.ToolTip ToolTip2 {
get { return m_tooltip2; }
set { m_tooltip2 = value; }
}
public System.Windows.Forms.ToolTip ToolTip3 {
get { return m_tooltip3; }
set { m_tooltip3 = value; }
}
public System.Windows.Forms.ToolTip ToolTip4 {
get { return m_tooltip4; }
set { m_tooltip4 = value; }
}
}
Then what I did was create an instance of this class inside my main form's Load event. Then I just assigned each of my 4 tooltips to the 4 tooltips in this class. Finally, I added this control to my panel. After doing all that, I could access the tooltips later by iterating through each control and looking for the TooltipMaster control.
Hope this makes sense!