avtel
asked on
How to refer to a Dynamically Created TextBlock later on to change its text?
Hi,
In an event handler in the code-behind, I created TextBlocks using a for-loop, and added them to cells in a grid. Now, I want to be able to refer to them later on in a different event handler, and iterate through another for-loop to change each one's Text value to something else
My problem is that I can't seem to refer to the specific TextBlocks in any way. I've searched through a lot of sites/forums/posts, but just can't seem to find something that'll work. Can anyone help?
In an event handler in the code-behind, I created TextBlocks using a for-loop, and added them to cells in a grid. Now, I want to be able to refer to them later on in a different event handler, and iterate through another for-loop to change each one's Text value to something else
My problem is that I can't seem to refer to the specific TextBlocks in any way. I've searched through a lot of sites/forums/posts, but just can't seem to find something that'll work. Can anyone help?
for (int i = 0; i < 6; i++)
{
for (int j = 1; j < 13; j++)
{
TextBlock genericTextBlock = new TextBlock();
genericTextBlock.Name = "TextBlock" + j.ToString() + i.ToString();
genericTextBlock.FontSize = 40;
genericTextBlock.VerticalAlignment = VerticalAlignment.Center;
genericTextBlock.HorizontalAlignment = HorizontalAlignment.Center;
genericTextBlock.Foreground = new SolidColorBrush(Colors.White);
Grid.SetColumn(genericTextBlock, j);
Grid.SetRow(genericTextBlock, i);
for (int k = 1; k < 13; j++)
{
TextBlock txt = FindControl("TextBlock" + k.ToString()) as TextBlock; // you will need to tweak this a little. Just pass the
// same name you created earlier.
txt.Text = "Assign any new value desired here";
}
private Control FindControl(string sControlName)
{
if (sControlName.Length == 0 || this.Controls.Find(sContro lName, true).Length == 0)
return null;
else
return this.Controls.Find(sContro lName, true)[0];
}
HTH
Ashok
{
TextBlock txt = FindControl("TextBlock" + k.ToString()) as TextBlock; // you will need to tweak this a little. Just pass the
// same name you created earlier.
txt.Text = "Assign any new value desired here";
}
private Control FindControl(string sControlName)
{
if (sControlName.Length == 0 || this.Controls.Find(sContro
return null;
else
return this.Controls.Find(sContro
}
HTH
Ashok
for (int k = 1; k < 13; j++)
{
TextBlock txt = FindControl("TextBlock" + k.ToString()) as TextBlock; // you will need to tweak this a little. Just pass the
// same name you created earlier.
if (txt != null) // this should not occur if you pass correct name as you created.
txt.Text = "Assign any new value desired here";
}
private Control FindControl(string sControlName)
{
if (sControlName.Length == 0 || this.Controls.Find(sContro lName, true).Length == 0)
return null;
else
return this.Controls.Find(sContro lName, true)[0];
}
HTH
Ashok
{
TextBlock txt = FindControl("TextBlock" + k.ToString()) as TextBlock; // you will need to tweak this a little. Just pass the
// same name you created earlier.
if (txt != null) // this should not occur if you pass correct name as you created.
txt.Text = "Assign any new value desired here";
}
private Control FindControl(string sControlName)
{
if (sControlName.Length == 0 || this.Controls.Find(sContro
return null;
else
return this.Controls.Find(sContro
}
HTH
Ashok
ASKER
ashol111:
I tried your method, and got the following exceptions:
"'MyProg.MainWindow' does not contain a definition for 'Controls' and no extension method 'Controls' accepting a first arguemnt of type 'MyProg.MainWindow' could be found (are you missing a using directive or an assembly reference?)"
and
"Cannot convert type 'System.Windows.Controls.C ontrol' to 'System.Windows.Controls.T extBlock' via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion, or null type conversion"
I tried your method, and got the following exceptions:
"'MyProg.MainWindow' does not contain a definition for 'Controls' and no extension method 'Controls' accepting a first arguemnt of type 'MyProg.MainWindow' could be found (are you missing a using directive or an assembly reference?)"
and
"Cannot convert type 'System.Windows.Controls.C
private Control FindControl (string sControlName)
{
if (sControlName.Length == 0 || this.Controls.Find(sControlName, true).Length == 0)
return null;
else
return this.Controls.Find(sControlName, true)[0];
}
private void ModeListBox_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
// TODO: Add event handler implementation here.
// This creates a holder ListBoxItem to take the SelectedItem from the ListBox. The "sender as ListBox" marks the generic object sender as the ListBox to get SelectedItem as, and "SelectedItem as ListBoxItem" gets the response as a ListBoxItem??
ListBoxItem holderLBImode = ((sender as ListBox).SelectedItem as ListBoxItem);
switch (holderLBImode.Content.ToString())
{
case "Show All" :
{
if (TuningListBox.SelectedIndex != -1)
{
InitializeTunings();
break;
}
else
break;
}
case "Hidden" :
{
for (int l = 0; l < 6; l++)
{
for (int m = 1; m < 13; m++)
{
TextBlock tempTB = FindControl("TextBlock" + m.ToString() + l.ToString()) as TextBlock;
tempTB.Text = "WORKS";
}
}
break;
Try using FindName():
http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.findname.aspx
Maybe something like?
for (int i = 0; i < 6; i++)
{
for (int j = 1; j < 13; j++)
{
TextBlock tb = (TextBlock)this.FindName(" TextBlock" + j.ToString() + i.ToString());
// ...use "tb" somehow...
}
}
http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.findname.aspx
Maybe something like?
for (int i = 0; i < 6; i++)
{
for (int j = 1; j < 13; j++)
{
TextBlock tb = (TextBlock)this.FindName("
// ...use "tb" somehow...
}
}
ASKER
Idle_Mind:
I tried that and get the following error:
"Unhandled Exception: System.NullReferenceExcept ion: Object reference not set to an instance of an object."
I tried that and get the following error:
"Unhandled Exception: System.NullReferenceExcept
ASKER
Idle_Mind:
I tried that and get the following error:
"Unhandled Exception: System.NullReferenceExcept ion: Object reference not set to an instance of an object."
I tried that and get the following error:
"Unhandled Exception: System.NullReferenceExcept
That means the control wasn't found...not sure how to proceed as I have done almost no WPF programming and I'm not sure how it's laid out.
Instead of "this", try putting the name of your grid:
TextBlock tb = (TextBlock)NameOfGridHere. FindName(" TextBlock" + j.ToString() + i.ToString());
TextBlock tb = (TextBlock)NameOfGridHere.
Idle_Mind is right. If control is not directly on the form, change this to where the control is.
If it is inside a GRID, change it to GRID.
Ashok
If it is inside a GRID, change it to GRID.
Ashok
BTW, I recently did a WinForms application where I used FindControl without any problem. The code I posted is tested in my application.
Ashok
Ashok
I'm not sure you can use FindControl() in a WPF application...I need to play with it more! =\
With wpf this method (FindControl) is now called FindName but it always returns a null.
Ashok
Ashok
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I had tried using the name of the Grid (and every other possible parent control) that directly contains the TextBlocks, but that returned the same exception. I just can't think of anything else to try.
Would it help if I posted my entire code-behind and the XAML?
I should mention I'm using Expression Blend 3 as the design editor.
Also, I tried Idle_Mind's List method, and got it to work for this particular situation. I'd still prefer to be able to refer to specific textblocks by the name I assign at creation though (since it is named according to row and column of the grid it's in). With the List method, I can refer by index, but correlating that to the textblock in a particular grid position isn't as smooth.
I'm dying to figure this out, because it has come up more than once.
Would it help if I posted my entire code-behind and the XAML?
I should mention I'm using Expression Blend 3 as the design editor.
Also, I tried Idle_Mind's List method, and got it to work for this particular situation. I'd still prefer to be able to refer to specific textblocks by the name I assign at creation though (since it is named according to row and column of the grid it's in). With the List method, I can refer by index, but correlating that to the textblock in a particular grid position isn't as smooth.
I'm dying to figure this out, because it has come up more than once.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Ok, that sounds like a good alternative. I'll give it a try and report back. I'm not sure what to do with the points here - I really want to figure out the FindName method, but your alternatives do what I need...I'm not sure how important the points are, but if they are important, what's the protocol?
By the way, what's the name of the WPF book you're reading? I'd like to find a good source to get a better handle on what I'm doing.
By the way, what's the name of the WPF book you're reading? I'd like to find a good source to get a better handle on what I'm doing.
I just started "WPF in Action" by Arlen Feldman and Maxx Daymon. I'm a WinForms guy so I'm stumbling around in WPF at the moment...LOL.
If someone posts the correct method on how to use FindName() then by all means give them the points! =)
A split is usually never objected to by participants though. I almost always give points to everyone involved in questions I ask but it's not necessary.
If someone posts the correct method on how to use FindName() then by all means give them the points! =)
A split is usually never objected to by participants though. I almost always give points to everyone involved in questions I ask but it's not necessary.
List TextBlocks = new List();
...
TextBlock genericTextBlock = new TextBlock();
...
TextBlocks.Add(genericText
Now you can use that list to iterate over them:
foreach(TextBlock tb in TextBlocks)
{
tb.xxx = yyy;
}
Put the List at the CLASS level, outside the method where the TextBlocks were created, so it will be accessible.
*I don't code in WPF, though, so I can't get more specific than that. =\