none
Strange SelectedItem behaviour when the same object is added multiple times to a listbox... any workaround?

    Question

  • I've noticed that if you have an items source that contains multiple instances of the same object, when one of the items is selected, the other are selected as well and they are not deselected. It seems like the listbox selects not only the item that is clicked but also all other instances of that same object. This is not the behaviour I'm after and I wonder if there is a workaround for this? Or do I need to create clones of all objects so that they are not referenced?

    Thanks for help!

    Monday, April 19, 2010 7:58 PM

Answers

  • Hi xkrja,

    If you select a item, the Selector object adds its reference to a InternalSelectedItemsStorage object. So if you select the references of the same item, the Selector object can not unselect the same old item (they are one item, can not separate them).

    Code in the Selector.cs (Bold is the path when we select the same item):

        private void UpdateSelectedItems()
        {
          IList selectedItemsImpl = this.SelectedItemsImpl;
          if (selectedItemsImpl != null)
          {
            InternalSelectedItemsStorage storage = new InternalSelectedItemsStorage(selectedItemsImpl.Count) {
              UsesItemHashCodes = this._selectedItems.UsesItemHashCodes
            };
            for (int i = 0; i < selectedItemsImpl.Count; i++)
            {
              object t = selectedItemsImpl[i];
              if (this._selectedItems.Contains(t) && !storage.Contains(t))
              {
                storage.Add(t);
              }
              else
              {
                selectedItemsImpl.RemoveAt(i);
                i--;
              }
            }
            foreach (object obj3 in (IEnumerable) this._selectedItems)
            {
              if (!storage.Contains(obj3))
              {
                selectedItemsImpl.Add(obj3);
              }
            }
          }
        }

    I recommend you to create the clones of all same items in the ListBox to avoid this strange behaviour.

    Sincerely,

    Bob Bao


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    • Marked as answer by xkrja Tuesday, April 20, 2010 11:23 AM
    Tuesday, April 20, 2010 10:02 AM
    Moderator

All replies

  • Hello,

     

    Why you need to have an items source with multiple instances of an object?

    Can you explain your scenario?

     

    Thanks.

    Monday, April 19, 2010 8:38 PM
  • Thanks for your reply.

    I'm using the listbox to represent a cue of "actions" that will be performed. These actions can be performed multiple times and it should be possible to place them anywhere in the cue. The action items in the list are added by dragging and dropping from another listbox that contains all avaliable actions.

    Thanks.

    Monday, April 19, 2010 9:13 PM
  • Hi xkrja,

    If you select a item, the Selector object adds its reference to a InternalSelectedItemsStorage object. So if you select the references of the same item, the Selector object can not unselect the same old item (they are one item, can not separate them).

    Code in the Selector.cs (Bold is the path when we select the same item):

        private void UpdateSelectedItems()
        {
          IList selectedItemsImpl = this.SelectedItemsImpl;
          if (selectedItemsImpl != null)
          {
            InternalSelectedItemsStorage storage = new InternalSelectedItemsStorage(selectedItemsImpl.Count) {
              UsesItemHashCodes = this._selectedItems.UsesItemHashCodes
            };
            for (int i = 0; i < selectedItemsImpl.Count; i++)
            {
              object t = selectedItemsImpl[i];
              if (this._selectedItems.Contains(t) && !storage.Contains(t))
              {
                storage.Add(t);
              }
              else
              {
                selectedItemsImpl.RemoveAt(i);
                i--;
              }
            }
            foreach (object obj3 in (IEnumerable) this._selectedItems)
            {
              if (!storage.Contains(obj3))
              {
                selectedItemsImpl.Add(obj3);
              }
            }
          }
        }

    I recommend you to create the clones of all same items in the ListBox to avoid this strange behaviour.

    Sincerely,

    Bob Bao


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    • Marked as answer by xkrja Tuesday, April 20, 2010 11:23 AM
    Tuesday, April 20, 2010 10:02 AM
    Moderator
  • I've noticed that if you have an items source that contains multiple instances of the same object, when one of the items is selected, the other are selected as well and they are not deselected. It seems like the listbox selects not only the item that is clicked but also all other instances of that same object. This is not the behaviour I'm after and I wonder if there is a workaround for this? Or do I need to create clones of all objects so that they are not referenced?

    Thanks for help!

    Your items are your objects, so if "one of them is selected" but you show that same item multiple times, I'm really not surprised that it the same item appears as selected in multiple places at once.

    If you have large objects, just make a light wrapper and put the same object in multiple wrappers, then use the wrapper as your item:

    public partial class MainWindow
    {
        class item
        {
            public MyType Data;
            //For presentation (e.g. "DisplayMember") you may also want to publish some of MyType's interface:
            public string LastName
            {
                get { return Data.LastName; }
            }
        }
        void foo()
        {
            var bigObj = DataAccessLayer.LoadMyType(4224);
            var c = new ObservableCollection<item>();
            for (int i = 0; i < 512; i++)
                c.Add(new item() { Data = bigObj });
            funkyList.ItemsSource = c;
        }
    }

    Wednesday, August 01, 2012 7:20 AM