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?
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);

Open in new window

avtelAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Mike TomlinsonMiddle School Assistant TeacherCommented:
Create a List and add them to it:

    List TextBlocks = new List();

    ...
        TextBlock genericTextBlock = new TextBlock();
        ...
        TextBlocks.Add(genericTextBlock);

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.  =\
0
AshokSr. Software EngineerCommented:
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(sControlName, true).Length == 0)
       return null;
    else
       return this.Controls.Find(sControlName, true)[0];
}
   
HTH
Ashok
0
AshokSr. Software EngineerCommented:
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(sControlName, true).Length == 0)
       return null;
    else
       return this.Controls.Find(sControlName, true)[0];
}
   
HTH
Ashok
0
Angular Fundamentals

Learn the fundamentals of Angular 2, a JavaScript framework for developing dynamic single page applications.

avtelAuthor Commented:
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.Control' to 'System.Windows.Controls.TextBlock' via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion, or null type conversion"
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;

Open in new window

0
Mike TomlinsonMiddle School Assistant TeacherCommented:
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...
        }
    }
0
avtelAuthor Commented:
Idle_Mind:

I tried that and get the following error:

"Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object."
0
avtelAuthor Commented:
Idle_Mind:

I tried that and get the following error:

"Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object."
0
Mike TomlinsonMiddle School Assistant TeacherCommented:
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.  
0
Mike TomlinsonMiddle School Assistant TeacherCommented:
Instead of "this", try putting the name of your grid:

    TextBlock tb = (TextBlock)NameOfGridHere.FindName("TextBlock" + j.ToString() + i.ToString());  
0
AshokSr. Software EngineerCommented:
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
0
AshokSr. Software EngineerCommented:
BTW, I recently did a WinForms application where I used FindControl without any problem.  The code I posted is tested in my application.

Ashok
0
Mike TomlinsonMiddle School Assistant TeacherCommented:
I'm not sure you can use FindControl() in a WPF application...I need to play with it more!  =\
0
AshokSr. Software EngineerCommented:
With wpf this method (FindControl) is now called FindName but it always returns a null.

Ashok
0
AshokSr. Software EngineerCommented:
I meant to say this.....

With wpf this method (FindControl) is now called FindName.

Ashok
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
avtelAuthor Commented:
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.
0
Mike TomlinsonMiddle School Assistant TeacherCommented:
If the List method worked for then you could simply use a Dictionary (instead of a List):
http://msdn.microsoft.com/en-us/library/xfhwa508.aspx

The Dictionary would allow you to add the TextBlocks using the NAME as the Key so you can directly retrieve them back out when needed:

    Dictionary TextBlocks = new Dictionary();

    ...
        TextBlocks.Add(genericTextBlock.Name, genericTextBlock);

You can get them back out later using something like:

    for (int i = 0; i < 6; i++)
    {
        for (int j = 1; j < 13; j++)
        {
            TextBlock tb = TextBlocks["TextBlock" + j.ToString() + i.ToString()];  
            // ...use "tb" somehow...
        }
    }

*Though I agree that there is probably a way to do it using a FindXXX() method but I don't have enough experience with WPF to help you out there.  (I'm reading a WPF book right now as a matter of fact).
0
avtelAuthor Commented:
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.
0
Mike TomlinsonMiddle School Assistant TeacherCommented:
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.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Programming Languages-Other

From novice to tech pro — start learning today.