NotDan
NotDan

Reputation: 32223

How can I access the ItemsPanel of a ListBox at runtime in silverlight?

How can I access the ItemsPanel of a ListBox at runtime in silverlight?

Upvotes: 1

Views: 660

Answers (2)

leifre
leifre

Reputation: 35

Building on terphi's solution, i changed it to return a list of the elements you are looking for as normally when your searching for a type, the listbox will have multiple items and multiple instances of what you are looking for. Additionally, I had issues with it finding things in the loaded event but used a dispatcher instead and it finds the items every time in testing.

private List<TextBlock> TextBlockList;

in the constructor, after associating the datasource with listbox:

Dispatcher.BeginInvoke(delegate { TextBlockList = GetFirstChildOfType<TextBlock>(listBox1); });


  List<T> GetFirstChildOfType<T>(DependencyObject visual) where T : DependencyObject
    {
        DependencyObject ControlCandidate;
        List<T> TempElements;
        List<T> TargetElementList = new List<T>();


        var itemCount = VisualTreeHelper.GetChildrenCount(visual);
        if (itemCount > 0)
        {
            for (int i = 0; i < itemCount; i++)
            {
                ControlCandidate = VisualTreeHelper.GetChild(visual, i);
                if (ControlCandidate is T)
                    TargetElementList.Add((T)ControlCandidate);
            }

            for (int i = 0; i < itemCount; i++)
            {
                TempElements = GetFirstChildOfType<T>(VisualTreeHelper.GetChild(visual, i));
                if (TempElements.Count > 0)
                    TargetElementList.AddRange(TempElements);
            }
        }

        return TargetElementList;
    }

Upvotes: 0

terphi
terphi

Reputation: 781

Given the following element declaration in XAML

<ListBox x:Name="LB" Loaded="LB_Loaded" />

There are two ways to achieve this, the easiest requires the Silverlight toolkit:

using System.Windows.Controls.Primitives;

private void LB_Loaded()
{
  var itemsPanel = LB.GetVisualChildren().OfType<Panel>().FirstOrDefault();
}

Or you can use the VisualTreeHelper and write the following recursive method:

T GetFirstChildOfType<T>(DependencyObject visual) where T:DependencyObject
{
  var itemCount = VisualTreeHelper.GetChildrenCount(visual);
  if (itemCount < 1)
  {
    return null;
  }

  for (int i = 0; i < itemCount; i++)
  {
    var dp = VisualTreeHelper.GetChild(visual, i);
    if (dp is T)
    {
      return (T)dp;
    }
  }
  for (int i = 0; i < itemCount; i++)
  {
    var dp = GetFirstChildOfType<T>(VisualTreeHelper.GetChild(visual, i));
    if (dp != null) return dp;
  }
  return null;
}

And get the result in a similar manner:

void ItemsPanelSample_Loaded(object sender, RoutedEventArgs e)
{
    var itemsPanel = GetFirstChildOfType<Panel>(LB);
}

Upvotes: 2

Related Questions