Search code examples
c#wpflistboxlistboxitem

WPF Unable to get ListBoxItem by item or by index after 7th item


I'm having a bit of a weird problem where I am trying to update the checked status of a checkbox contained inside a ListBoxItem, I am unable to get a ListBoxItem after the 7th item I've tried several methods to get this to work, as seen in the below method. itemIndex each time does have a positive value (so the I know the item is being found), but why It cant get the listboxitem I do not know

private IEnumerable<CheckBox> GetListBoxItemCheckBoxes(object item)
{
    var itemIndex = LstItems.Items.IndexOf(item);
    var selectedListBoxItem = LstItems.ItemContainerGenerator.ContainerFromIndex(itemIndex) as ListBoxItem;
    var selectedListBoxItemCheckBoxes = selectedListBoxItem?.FindVisualChildrenOfType<CheckBox>();

    if (selectedListBoxItemCheckBoxes == null)
    {
        selectedListBoxItem = LstItems.ItemContainerGenerator.ContainerFromItem(item) as ListBoxItem;
        selectedListBoxItemCheckBoxes = selectedListBoxItem?.FindVisualChildrenOfType<CheckBox>();

        if (selectedListBoxItemCheckBoxes == null)
        {
            itemIndex = LstItems.ItemContainerGenerator.Items.IndexOf(item);
            selectedListBoxItem = LstItems.ItemContainerGenerator.ContainerFromIndex(itemIndex) as ListBoxItem;
            selectedListBoxItemCheckBoxes = selectedListBoxItem?.FindVisualChildrenOfType<CheckBox>();
        }
    }

    return selectedListBoxItemCheckBoxes;
}

I think that this may be to do with the timing of when I am trying to set the checkbox states as I am trying to do it after I have added that item? I've read a few questions relating to this area on SO but so far none of have been able to help me with my problem, I thought this answer might be close.. but It gave me the same result: https://stackoverflow.com/a/23501378/1800140

The items are not bound, they are added using ListBox.Items.Add (not too familiar with binding).

I am also doing this in a background thread as I need to refresh the contents of my listbox regularly and need to make an api call to do so.

The method that is being used for updating the contents of my listbox is as below. SetItemChecked calls the first method to get the checkbox, however this starts to return null after the 7th item

public void ResetAndAddItems<T>(IEnumerable<T> items, string displayByProperty = "",
        Func<T, string> displayByFunc = null,
        Dictionary<string, bool> checkedStates = null,
        Func<ListItem<T>, Dictionary<string, bool>, bool> checkedStatesKeyFunc = null)
{
    Dispatcher.Invoke(() =>
    {
        LstItems.Items.Clear();
    });

    var listedItems = items?.ToList();

    if (listedItems == null || !listedItems.Any())
    {
        return;
    }

    foreach (var item in listedItems)
    {
        var listItem = new ListItem<T>
        {
            DisplayByProperty = displayByProperty,
            DisplayByFunc = displayByFunc,
            Item = item
        };

        Dispatcher.Invoke(() =>
        {
            LstItems.Items.Add(listItem);
            if (checkedStates != null && checkedStatesKeyFunc != null)
            {
                SetItemChecked(item, checkedStatesKeyFunc(item as ListItem<T>, checkedStates));
            }
        });
    }
}

Solution

  • To fix this issue, I had to result to binding.

    The issue is that because only 7 items are display on the listview at once only 7 items are drawn, to get around this I can scroll to the next item after the 7th item and so on however this was noticeably slower.