-1

I currently have a class object that is bound to a listboxitem. Before I used to get the other objects inside the ListBoxItem by clicking a button and accessing its parent, but now I need to gather the objects without clicking the buttons or labels, just by its class.

I've tried to gather the ListBoxItem with its index and its class binding, but both of them is giving me a null value:

ObservableCollection<ClassBinding> classList = new ObservableCollection<ClassBinding>();
... adding items here to the collection;
listBox.ItemsSource = classList;
ListBoxItem lbi = (ListBoxItem)listBox.ItemContainerGenerator.ContainerFromIndex(index);

Is there another way to access the listboxitem to later gather the other objects by using the function FindName(...)?

Debug:

TextBlock delay = lbi.FindName("lblDelay") as TextBlock;

Error:

Output: Exception thrown: 'System.InvalidOperationException' in WindowsBase.dll
Sickness
  • 33
  • 1
  • 8

2 Answers2

1

A ListBox is virtualized by default, see Displaying large data sets.

Typically, you do not have to display all the items at the same time; instead you display a subset, and the user scrolls through the list. In this case, it makes sense to use UI virtualization, which means the item container generation and associated layout computation for an item is deferred until the item is visible.

In other words, you get null, because the ListBoxItem in question is not yet visible and realized. The only reliable way to get around this is to disable virtualization to force instantiation of all items. Although you can then access each item, this can result in bad performance for large collections, since all items are loaded when the ListBox is loaded and all items are held in memory which increases the memory footprint.

<ListBox x:Name="listBox" VirtualizingStackPanel.IsVirtualizing="False">

Accessing child controls, e.g. in data templates by name with FindName(...) does not work in ItemsControls like ListBox. You will have to walk the visual tree to get the controls, see:


In general, it is not a good idea to deal with controls in an items control directly. It is much easier to use data-binding, where you will not have any issues with containers and virtualization as you do not access them directly. Furthermore, your code will be simplified and you do not need to assume a visual structure.

For more information and examples on this topic, you can refer to:

thatguy
  • 21,059
  • 6
  • 30
  • 40
0

In order to find another solution/idea for this I came up with the INotifyPropertyChanged that can be added inside the classes, so there's no need to remove the ItemsSource from the list box, just hook the items source at the load of the program and then you can change the data inside the collection.

I used the code from here: INotifyPropertyChanged and ObservableCollection WPF

I didn't need to access the text blocks, just hooked some bindings to the objects and was able to do UI changes from just changing the values of the classes.

Sickness
  • 33
  • 1
  • 8