4
votes

Listbox is updated every sec and during work I need to select some of it's items and execute a command, which is impossible, because listbox is updated and loses it's selected item.

ObservableCollection is the ViewModel of my list.

I have some options in mind and perhaps there are better solutions:

  1. Detect new items in the list to be propagated and add new items to ObservableCollection without reinitializing ObservableCollection

  2. Detect changes in the old items and updated their fields if necessary.

This is somewhat cumbersome, though not difficult, but are there any other options?

Update, solution that I have

I've chosen the 3-d part: before an update has started, I save selected index of sorted collection and load a new collection and compare vs. old collection. I Know, this is not efficient, but for the current application this fits quite well: collections will never be more than some hundreds, ordinarily, no more 100. Each element of collection supports eager and lazy loading. And if there are changed items, they load their content from server, while other remain intact. And then I update observable collection, update changed items from server and set selected index in the viewmodel. Selecting an item manually solves the problem of losing focus after update.

4

4 Answers

2
votes

Save the selected item's key before the list is updated. Find it in the new version of the list, and re-select it. Don't rely on the original reference, and allow for some other fellow removing it from the new list to select from.

2
votes

This sometimes happens if you change the order of the items in the list box's ItemsSource. When you remove the item temporarily to insert it somewhere else, WPF will prematurely set the SelectedItem to null. Then when you add it back in, it won't be selected.

Here's a workaround in the form of a behavior that you can attach to your list box.

http://www.codeproject.com/Tips/802806/Preserve-the-Selected-Item-of-a-WPF-List-Box

0
votes

I'm thinking of changing your binding collection to a new instance of the current collection. Once you start selecting items. once you finish set the binding back to the original collection

-2
votes

What if you

  1. add a class to your select:

    <select title="" id="" class="initMySelect"> </select>

  2. target the class to repopulate the select

Example from an object:

  var object={
  "6db01de6-a1e8-4ea6-bf01-4562b56468b9": {
    "UID": "6db01de6-a1e8-4ea6-bf01-4562b56468b9",
    "name": "aa",
    "description": "aa"
  },
  "284c3172-268a-4342-d3f0-d00fafd3d482": {
    "UID": "284c3172-268a-4342-d3f0-d00fafd3d482",
    "name": "bb",
    "description": "bb"
  },
  "b124f4df-6caa-43e8-eb97-536076b4832b": {
    "UID": "b124f4df-6caa-43e8-eb97-536076b4832b",
    "name": "cc",
    "description": "cc"
  },
  "c934634a-0775-41bd-d72a-d8900ebcbdd1": {
    "UID": "c934634a-0775-41bd-d72a-d8900ebcbdd1",
    "name": "dd",
    "description": "dd"
  },
  "fb5b8dcb-b9fb-405d-9fcf-3f551727459a": {
    "UID": "fb5b8dcb-b9fb-405d-9fcf-3f551727459a",
    "name": "ee",
    "description": "ee"
  },
  "a98f3449-bb55-46e3-b9ce-f9e2dd6d74a9": {
    "UID": "a98f3449-bb55-46e3-b9ce-f9e2dd6d74a9",
    "name": "ff",
    "description": "ff"
  }
}
function initMySelect(value) {
    var options = "";
    var selected = "";

    $.each(object, function(k, v) {
      if (value === v.UID) {
        selected = 'selected = "selected"';
      } else {
        selected = "";
      }
      options += '<option ' + selected + ' value=' + v.UID + '>' + v.name + '</option>';
    });

  $('.initMySelect').html(options);
}
  1. Whatever CRUD you making, will reinitialise the class, meaning the class will hold all the Up-to-date changes. so after any add, update, delete, exe your function
initMySelect();

when viewing your select the selected index will still be there as selected and the extra Crud changes u made will appear in your select. 4. Function to add event listener on button which send the selected value to initMySelect

var el = document.getElementById("repopulateSelect");
el.addEventListener("click", function() {
    initMySelect(document.getElementById("selectTest").value);
}, false);

JSFiddle link: