14

I created a ListBox that has a DataTemplate as Itemtemplate. However, is there an easy way to access the generated UIElement instead of the SelectedItem in codebehind?

When I access SelectedItem, I just get the selected object from my ItemsSource collection. Is there a way to access the UIElement (ie. the element generated from the DataTemplate together with the bound object)?

Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
Joachim Kerschbaumer
  • 9,695
  • 7
  • 49
  • 84

2 Answers2

14

You are looking for the ItemContainerGenerator property. Each ItemsSource has an ItemContainerGenerator instance. This class has the following method that might interest you: ContainerFromItem(object instance).

Once you have a handle to the ListBoxItem, you can go ahead and browse the logical and visual tree. Check out Logical Tree Helper and Visual Tree Helper.

Like Andy said in the comments, just because the item exists in your collection doesn't mean a container has been generated for it. Any kind of virtualizing panel scenario will raise this issue; UIElements will be reused across the different items. Be careful with that as well.

Pavel Anikhouski
  • 21,776
  • 12
  • 51
  • 66
Szymon Rozga
  • 17,971
  • 7
  • 53
  • 66
  • Note that just because an item has been added to the control, that doesn't mean that its UI container has been generated yet. Make sure to account for the case where there is no UI container yet. – Andy Mar 04 '09 at 17:34
  • I am writing in c# and WPF and this property doesn't appear under ListBox.ItemsContainer How do I get the instance for this listbox? – sprite Jun 30 '10 at 18:06
  • @size, do you have a solution for my question? http://stackoverflow.com/questions/6148279/record-items-visible-to-user-in-listbox (+250 bounty) – tofutim May 29 '11 at 16:13
  • 6
    Just for reference here is the full code I got working: `var container = ListBox.ItemContainerGenerator.ContainerFromItem(ListBox.SelectedItem) as FrameworkElement; if (container != null) container.Focus();` – Bodekaer Jan 18 '12 at 12:55
5

siz, Andy and Bodeaker are absolutely right.

Here is how I was able to retrieve the textbox of the listbox's selected item using its handle.

var container = listboxSaveList.ItemContainerGenerator.ContainerFromItem(listboxSaveList.SelectedItem) as FrameworkElement;
if (container != null)
{
    ContentPresenter queueListBoxItemCP = VisualTreeWalker.FindVisualChild<ContentPresenter>(container);
    if (queueListBoxItemCP == null)
        return;

    DataTemplate dataTemplate = queueListBoxItemCP.ContentTemplate;

    TextBox tbxTitle = (TextBox)dataTemplate.FindName("tbxTitle", queueListBoxItemCP);
    tbxTitle.Focus();
}

(Note: Here, VisualTreeWalker is my own wrapper over VisualTreeHelper with various useful functions exposed)

vamosrafa
  • 252
  • 2
  • 13
  • 21