in WPF It it possible to change a text box's font size during runtime?
i tried to do that:
foreach (Control ctrl in gridArray[i].Children)
{
if(ctrl.GetType() == typeof(TextBox))
{
(TextBox)ctrl.FontSize = (double)5;
}
}
but it didnt work
The cast does not have a high precedence, your code effectively tries to cast the value in ctrl.FontSize to TextBox, you need to add parenthesis (and the double cast is superfluous):
((TextBox)ctrl).FontSize = 5;
Further the way you check the type of the control is not such a good idea, use is instead. Otherwise sublasses of TextBox are not included.
if (ctrl is TextBox)
Further as you do not only care about the type and cast as well to interact with the TextBox class interface you may as well use as:
var textBox = ctrl as TextBox;
if (textBox != null)
textBox.FontSize = 5;
This also conveniently gets rid of the parenthesis jungle.
Related
foreach(Control c in tabAppreciation.Controls)
{
if(c is Button)
{
if((Button)c.Text.ToString()==0)
{
c.BackColor = Color.Green;
}
}
}
I'm getting this error:
Cannot convert type 'string' to 'System.Windows.Forms.Button'
I wanna compare the text of each Button with something and if it matches, change the color of the button, but it seems like I'm not doing it right at all... Can someone help me please?
You could change your code to a simpler
foreach(Button b in tabAppreciation.Controls.OfType<Button>())
{
if(b.Text=="0")
{
b.BackColor = Color.Green;
}
}
This enumerates all the controls of type Button inside the tabAppreciation controls collection and your loop is strongly typed so you don't need anymore the test for Is Button. Notice also that the Text property is already a string and thus applying ToString() makes no sense. Finally a string should be compared to a string (put the zero between double quotes not single quotes that denote a char)
FYI: To use OfType<T>, if it is not already there, you need to add a using System.Linq; directive at the top of in your code file.
Try this:
tabAppreciation
.Controls
.Select( c => c as Button )
.Where( c => c != null )
.Where( b => b.Text.ToString() == "0" )
.ForEach( b => b.BackColor = Color.Green )
;
Arguable easier to read and would have made the issue behind the question less relevent.
foreach(Control c in tabAppreciation.Controls)
{
Button button = c as Button
if(button != null && button.Text == "0")
{
button.BackColor = Color.Green;
}
}
You are almost there. If you do have button controls in the tabAppreciation.Controls collection, then all you need to do is compare the text (you stated in your question: I wanna compare the text of each Button with something and if it matches). So change your code to something like this:
foreach(Control c in tabAppreciation.Controls)
{
if(c is Button)
{
Button button = (Button)c;
if(button.Text=="Button text")
{
c.BackColor = Color.Green;
}
}
}
I am not sure why you check if your text equals a number. If your button text shows a number, then you need to note, that there is a difference between "0" and 0 - the first is of type string and the second of type int (and '0' is again a different type - character).
The ToString() method always returns a string, so it should be easy to construct the condition (rule of thumb) - both sides between a condition operator should have the same type, so after ToString()= it has to come a string - "0" or "text ...".
(Button)c.Text.ToString() is trying to cast the Text property into a button. That is your error. You actually don't need to cast the c object into a Button since the Text property is inherited from ButtonBase which overrides the Text property from the Control Class. The .NET framework is smart enough to know that you mean the overridden Text property not the base one.
To access the c as a button you need to make a new button variable and set its value as c; Button b = c as Button.
You also don't need to call ToString() on a string.
I'm trying to create my custom control for:
(numeric updown)
I want to use the value in the control to offset the position of a certain element (which is set using "targetElement" on the control's properties). But since settings are stored as strings, I only have the string value.
For example: If the user sets "targetElement" as label1, I want to offset the position of label1 using BobbyUpDown1.targetElement.Location.x, but since targetElement is storing a string of the ID of the element, it won't let me do that.
How can I grab the reference to the label1 (that the user input) from the targetElement property?
Do this:
Control c = this.Controls["YourLabelName"];
if (c != null)
{
c.Location = new Point(newXLocationForYourLabel, c.Location.Y);
}
Here this is the Form
I have multiple XAML TextBoxes, each of which manipulate a corresponding value in an array, when the value in the TextBox is changed, using a C# method which dynamically checks which TextBox has called the method.
<TextBox x:Name="_0_0" TextChanged="_x_y_TextChanged"/>
<TextBox x:Name="_0_1" TextChanged="_x_y_TextChanged"/>
<TextBox x:Name="_0_2" TextChanged="_x_y_TextChanged"/>
// And so on.....
each of which manipulate a corresponding value in an array, when the value in the TextBox is changed, using a C# method which dynamically checks which TextBox has called the method.
private void _x_y_TextChanged(object sender, TextChangedEventArgs e)
{
TextBox current = (TextBox)sender;
string currentname = current.Name;
string rowstring = currentname.Substring(1, 1);
string columnstring = currentname.Substring(3, 1);
int row = Convert.ToInt32(rowstring);
int column = Convert.ToInt32(columnstring);
// I've then detected the name of the textbox which has called it...
So this information can be used to dynamically store information from a TextBox in a corresponding array index - or whatever you want to do with it...
My question however, is:
How can I create a method which uses index locations in my array, to call the relevant TextBox and update its text?
Use FindName(string) to find the text box by name as follows (where container is a control that contains all of the text boxes):
private void UpdateTextBox(int row, int column, string text)
{
TextBox textBox = container.FindName("_" + row + "_" + column) as TextBox;
if(textbox != null)
{
textbox.Text = text;
}
}
There are two ways you might go:
If you have a lot of data to manage, or if you can't predict the length of the array, it would be better to bind to a collection instead of manually poking data into and out of an array. If you create a class derived from ObservableCollection instead of using an array the data <> ui relationship is pretty trivial.
if you really need to do this manually, maybe it would be better to stick the index into the 'tag' field of your text boxes. You could (a) see it clearly in your xaml, (b) parse it easily and (c) if you used a variation on the formula here:
Find all controls in WPF Window by type
you could iterate over the textboxes in window and find the right one by looking at its tag index:
foreach (TextBox t in FindVisualChildren<TextBox>(this))
{
if ((int) t.Tag) == my_index )
{
t.Text = "my_text_goes_here";
}
}
I would go in the direction of the answer I gave on this question:
form anchor/dock
In short, I would create a class that holds the actual values and then create a collection that holds information classes.
Then I would not use the event "TextChanged" on the TextBoxes, rather "sniff" for changes on the Dependency Property used to hold the text. This can easily be done in the Dependency Property.
Last, I would use an ItemsControl or ItemsPresenter to show the controls. Number of controls will follow number of items in the collection.
I suggest using MVVM pattern, data template, and ItemsControl for handling this problem effectively.
just feeling that i'm wasting loops here = CPU time, and was wondering if there's a way to optimize this code, or just minimize it.
Basically what the code does is, goes trough every controls inside the editOkkInfo control.
checking if the current control is an textbox, if yes, then it will perform some stuff, if no it will jumps to next if-statement. This next statement checks if we have counted 14 times(since i only have 14 textboxes), if not 14, then the loop continues, if counted 14, then the loop breaks.
Any help is appreciated, thanks in advance, and here is the code, cheers.
iterate = 0;
foreach (System.Web.UI.Control ctrl in this.editOkkInfo.Controls)
{
if (ctrl is TextBox)
{
tb = (TextBox)this.FindControl(ctrl.ClientID.ToString());
tb.Text = dt.DefaultView[0][iterate++].ToString();
}
if (iterate == 14)
break;
}
There is no need to use FindControl, as you already have the control. Just cast it:
iterate = 0;
foreach (System.Web.UI.Control ctrl in this.editOkkInfo.Controls)
{
if (ctrl is TextBox)
{
tb = (TextBox)ctrl;
tb.Text = dt.DefaultView[0][iterate++].ToString();
}
if (iterate == 14)
break;
}
An additional readability improvement will do away with the looping over all controls and the is test:
foreach (TextBox ctrl in this.editOkkInfo.Controls)
{
ctrl.Text = dt.DefaultView[0][iterate++].ToString();
if (iterate == 14)
break;
}
You can save your FindControl() parsing by casting the ctrl variable:
tb = (TextBox) ctrl;
tb.Text = //...
And, we should know if editOkkInfo.Controls are created by code or declared in aspx page. If the former is true, you can save a reference to such objects in a variable, then using it instead of looping.
if (ctrl is TextBox)
{
tb = (TextBox)ctrl;
}
this should be enough, you are looking the TextBox using FindControl, knowing that you have it.So, you can just cast the the control to TextBox
I have seen one faster way to find all controls of specific type rather than looping.
This seems more efficient.
Using linq to get list of web controls of certain type in a web page
Hope that helps
Milind
I think instead foreach is better a while, because a while wont check all the controls, until the amount is 14 (could or not check all the controls, depends!)
I am writing a C#/ASP.Net web application and I have a large number of text boxes that need to be set to variable values in the code behind. Currently I am doing the following:
AspTextBox0.Text = codeBehindVariable[0];
AspTextBox1.Text = codeBehindVariable[1];
AspTextBox2.Text = codeBehindVariable[2];
AspTextBox3.Text = codeBehindVariable[3];
…
Is there an easy way to do this in a simple “for” loop??
This is a very simplified example, the real program has a switch case and some other testing that needs to be performed at the time the variable is assigned. Therefore, a “for” loop would drastically simplify the writing and maintainability of the code. Back in the good-old-days of VB6 and control arrays this was a piece of cake.
The good old days of VB6 are long gone and better don't come back.
Create a control array or better a List<TextBox> yourself:
var textBoxes = new List<TextBox> {
AspTextBox0,
AspTextBox1,
// ...
};
Then Zip it with the codeBehindVariable:
textBoxes.Zip(codeBehindVariable,
(textBox, variable) => textBox.Text = variable);
Or, if you prefer a for loop:
for ( int i = 0; i < codeBehindVariable.Length; i++ )
{
textBoxes[i].Text = codeBehindVariable[i];
}
Keep in mind that in the for loop you will have to make sure that both textBoxes and codeBehindVariable have the same number of items (or make the loop run only over the shortest list's amount of entries). The Zip function will take care of this by itself.
Assuming you are in a class that implements System.Web.UI.Page you can try to look up the control to find the one you want like so:
for (int i = 0; i <= codeBehindVariable.Length; i++)
{
var textBox = FindControl("AspTextBox" + i, false);
if(textBox != null)
{
textBox.Text = codeBehindVariable[i];
}
}
you can do something like this...
int i = 0;
foreach (Control ctrl in this.Controls)
{
if (ctrl is TextBox)
{
TextBox tempTextBox = (TextBox)ctrl;
tempTextBox.Text = codeBehindVariable[i];
i++;
}
}