1

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));
            }
        });
    }
}
Community
  • 1
  • 1
Andy
  • 823
  • 5
  • 17
  • 37

2 Answers2

2

UI Virtualization is set to True by default on ListBoxes. And if UI Virtualization is enabled, containers will only be created for the visible items. Try setting this attached property:

VirtualizingStackPanel.IsVirtualizing="False" 
Hej
  • 91
  • 4
  • Yes it will, load time and memory consumption will increase. However, that is the only way you can ensure all containers are available everytime for all the ListBoxItems. May I know what you are trying to accomplished? Do you really need the checkbox instance or just the checked state? If the latter, databinding is the solution. – Hej Mar 23 '17 at 09:26
  • Trying to set the checkbox checked state, not 100% sure on bindings so the only way I know to do this is to get the instance and set it myself – Andy Mar 23 '17 at 09:40
  • I see, well DataBinding is the correct approach. But maybe you can try measuring performance first when virtualization is not enabled. It is usually okay if you do not expect items by the thousands and your item template is not that deep. – Hej Mar 23 '17 at 10:21
  • Just got round to giving this a try, same problem unfortunatly – Andy Mar 23 '17 at 12:50
0

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.

Andy
  • 823
  • 5
  • 17
  • 37