0

I have many labels as children of many different stack panels which are all children of a list box, and I need to reference one of these labels were the Content.toString() == "criteria". In other words, traversing the visual tree in WPF would be a ball ache because there are many parent/child methods to run. Is there a way of finding one of these labels on my window without it having a name and assuming I don't know how far 'down' it is in the tree? Maybe there's an item collection of everything in a window (without heirarchy) that I can run some LINQ against??

If you're wondering why I don't have a name for the labels - it's because they are generated by a data template.

Thanks a lot,

Dan

H.B.
  • 166,899
  • 29
  • 327
  • 400
  • 2
    Are you concerned that traversing the visual tree will cause a performance issue? – Daniel Pratt Jan 09 '12 at 15:03
  • Not necessarily, I'm only going to need to do this once on application starting. It's more the concern with how elegant my code isn't going to be once I've stepped up and down the tree that many times. –  Jan 09 '12 at 15:06

4 Answers4

2

Seems like what you're looking for: Find DataTemplate-Generated Elements

Anatolii Gabuza
  • 6,184
  • 2
  • 36
  • 54
  • It's certainly close. Do you know if there's anyway of dynamically naming the object in a datatemplate? I can't seem to bind to the Name property. Thanks a lot. –  Jan 09 '12 at 15:18
  • @DanielMcNulty, Do you mean unique name for each object in Page scope (not just within Template)? – Anatolii Gabuza Jan 09 '12 at 15:23
  • 1
    Also look at [`VisualTreeHelper`](http://msdn.microsoft.com/en-us/library/system.windows.media.visualtreehelper.aspx). You can query Ancestors or Descendants using Linq. – Anatolii Gabuza Jan 09 '12 at 15:28
  • Well, unique name for every object. So say for example I'm binding a list of Activity classes to a listbox. And this activity class has a JobNumber property. How can I set a stackpanel's name (in the listbox's datatemplate) to equal (i.e. bind to) the JobNumber property? –  Jan 09 '12 at 15:32
1

I don't know whether this will help or not:

If you are looking for a specific label in each stack panel in the listBox, then you could just look for that specific label with its specific name and compare the content.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
user963602
  • 41
  • 1
  • 2
  • 13
  • I don't have a name for any of the labels. It's safe to assume I have no name for the stack panel's either. These are all generated by data templates. –  Jan 09 '12 at 14:56
1

i think this code might be usefull for you:

        foreach (Control control in this.Controls)
        {
            if (control.GetType() == typeof(Label))
                if (control.Text == "yourText")
                {
                    // do your stuff
                }
        }

i used This question as my base

Community
  • 1
  • 1
Moonlight
  • 708
  • 1
  • 7
  • 18
  • The Control's property doesn't seem to exist!? i.e. this.Controls is invalid. –  Jan 09 '12 at 15:22
  • hmm weird, although im using winforms, wpf should have a collection of the added controls also – Moonlight Jan 09 '12 at 15:28
1

I made a slight change to the code that @anatoliiG linked in order to return all the child controls of the specified type (instead of the first one):

private IEnumerable<childItem> FindVisualChildren<childItem>(DependencyObject obj)
    where childItem : DependencyObject
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(obj, i);

        if (child != null && child is childItem)
            yield return (childItem)child;

        foreach (var childOfChild in FindVisualChildren<childItem>(child))
            yield return childOfChild;
    }
}

With this function you could do something like this:

var criteriaLabels =
    from cl in FindVisualChildren<Label>(myListBox)
    where cl.Content.ToString() == "criteria"
    select cl;

foreach (var criteriaLabel in criteriaLabels)
{
    // do stuff...
}
Daniel Pratt
  • 12,007
  • 2
  • 44
  • 61