protected internal override void HandleIsSelectedChanged(bool oldValue, bool newValue) { base.HandleIsSelectedChanged(oldValue, newValue); if (INTERNAL_VisualTreeManager.IsElementInVisualTree(this)) { //todo: remove what's inside the "if" above once we will have defined a default style for the ItemsControl, that does about the same thing. if (INTERNAL_ParentSelectorControl != null) { if (INTERNAL_ParentSelectorControl is MultiSelector) { var parent = (MultiSelector)INTERNAL_ParentSelectorControl; if (newValue) { if (!INTERNAL_WorkaroundObservableCollectionBugWithJSIL.Contains(parent.SelectedItems, this.INTERNAL_CorrespondingItem)) { INTERNAL_WorkaroundObservableCollectionBugWithJSIL.Add(parent.SelectedItems, this.INTERNAL_CorrespondingItem); } } else { if (INTERNAL_WorkaroundObservableCollectionBugWithJSIL.Contains(parent.SelectedItems, this.INTERNAL_CorrespondingItem)) { INTERNAL_WorkaroundObservableCollectionBugWithJSIL.Remove(parent.SelectedItems, this.INTERNAL_CorrespondingItem); } } } } } }
void listBoxItem_Click(object sender, RoutedEventArgs e) { #if MIGRATION ModifierKeys modifiersKey = new ModifierKeys(); modifiersKey = Keyboard.Modifiers; bool isControl = modifiersKey.HasFlag(ModifierKeys.Control); bool isShift = modifiersKey.HasFlag(ModifierKeys.Shift); #else VirtualKeyModifiers modifiersKey = new VirtualKeyModifiers(); modifiersKey = Keyboard.Modifiers; bool isControl = modifiersKey.HasFlag(VirtualKeyModifiers.Control); bool isShift = modifiersKey.HasFlag(VirtualKeyModifiers.Shift); #endif SelectorItem selectorItem = (SelectorItem)sender; //--------------------------------------------------- //Single //--------------------------------------------------- if (SelectionMode == SelectionMode.Single) { INTERNAL_WorkaroundObservableCollectionBugWithJSIL.Clear(SelectedItems); SelectedItems.Add(selectorItem.INTERNAL_CorrespondingItem); } //--------------------------------------------------- //Multiple //--------------------------------------------------- else if (SelectionMode == SelectionMode.Multiple) { //If click on an already selected element if (INTERNAL_WorkaroundObservableCollectionBugWithJSIL.Contains(SelectedItems, selectorItem.INTERNAL_CorrespondingItem))//if we are in a multiple mode and the currently selected element is the one we clicked, we want to unselect it. { INTERNAL_WorkaroundObservableCollectionBugWithJSIL.Remove(SelectedItems, selectorItem.INTERNAL_CorrespondingItem); } //else click on a new element else { SelectedItems.Add(selectorItem.INTERNAL_CorrespondingItem); } } //--------------------------------------------------- //Extended //--------------------------------------------------- else if (SelectionMode == SelectionMode.Extended) { int indexOfClickedItem = ConvertToListOfObjectsOrNull(_actualItemsSource).IndexOf(selectorItem.INTERNAL_CorrespondingItem); //todo-perfs: this is O(N). //if Shift is pressed if (isShift) { int indexStart = _indexOfLastClickedItemWithoutShiftKey; int indexEnd = indexOfClickedItem; int change; if (indexStart > indexEnd) { change = indexEnd; indexEnd = indexStart; indexStart = change; } int index = 0; //clear before adding INTERNAL_WorkaroundObservableCollectionBugWithJSIL.Clear(SelectedItems); foreach (object item in _actualItemsSource) { if (indexStart <= index && index <= indexEnd) { if (!INTERNAL_WorkaroundObservableCollectionBugWithJSIL.Contains(SelectedItems, item)) //todo-perfs: use a dictionary { SelectedItems.Add(item); } } index++; } } //if Control is pressed else if (isControl) { //If click on an already selected element if (INTERNAL_WorkaroundObservableCollectionBugWithJSIL.Contains(SelectedItems, selectorItem.INTERNAL_CorrespondingItem))//if we are in a multiple mode and the currently selected element is the one we clicked, we want to unselect it. { INTERNAL_WorkaroundObservableCollectionBugWithJSIL.Remove(SelectedItems, selectorItem.INTERNAL_CorrespondingItem); } //else click on a new element else { SelectedItems.Add(selectorItem.INTERNAL_CorrespondingItem); } } //Nothing is pressed else { INTERNAL_WorkaroundObservableCollectionBugWithJSIL.Clear(SelectedItems); SelectedItems.Add(selectorItem.INTERNAL_CorrespondingItem); } if (!isShift) { _indexOfLastClickedItemWithoutShiftKey = indexOfClickedItem; } } else { throw new NotSupportedException("SelectionMode is not Single, Multiple or Extended."); } }
void listBoxItem_Click(object sender, RoutedEventArgs e) { _skipSelectionChangedEvent = true; // Note: we keep this to true for the whole method since this method will handle the SelectionChanged event itself (this way we don't risk having multiple calls to SelectionChanged when adding multiple elements for example). //object[] oldItems = null; bool hasSelectionChanged = false; List <object> addedItems = new List <object>(); List <object> removedItems = new List <object>(); #if MIGRATION ModifierKeys modifiersKey = new ModifierKeys(); modifiersKey = Keyboard.Modifiers; bool isControl = modifiersKey.HasFlag(ModifierKeys.Control); bool isShift = modifiersKey.HasFlag(ModifierKeys.Shift); #else VirtualKeyModifiers modifiersKey = new VirtualKeyModifiers(); modifiersKey = Keyboard.Modifiers; bool isControl = modifiersKey.HasFlag(VirtualKeyModifiers.Control); bool isShift = modifiersKey.HasFlag(VirtualKeyModifiers.Shift); #endif SelectorItem selectorItem = (SelectorItem)sender; //--------------------------------------------------- //Single //--------------------------------------------------- if (SelectionMode == SelectionMode.Single) { if (SelectedItem != selectorItem.INTERNAL_CorrespondingItem) //todo: SelectedItems contains more than one element (I'm pretty sure we ignore is as long as the clicked element is the SelectedItem). { HashSet <object> selectedItemsHashSet = CopyToHashSet(SelectedItems); INTERNAL_WorkaroundObservableCollectionBugWithJSIL.Clear(SelectedItems); SelectedItems.Add(selectorItem.INTERNAL_CorrespondingItem); addedItems.Add(selectorItem.INTERNAL_CorrespondingItem); if (selectedItemsHashSet.Contains(selectorItem.INTERNAL_CorrespondingItem)) { selectedItemsHashSet.Remove(selectorItem.INTERNAL_CorrespondingItem); } foreach (object item in selectedItemsHashSet) { removedItems.Add(item); } hasSelectionChanged = true; } } //--------------------------------------------------- //Multiple //--------------------------------------------------- else if (SelectionMode == SelectionMode.Multiple) { //If click on an already selected element if (INTERNAL_WorkaroundObservableCollectionBugWithJSIL.Contains(SelectedItems, selectorItem.INTERNAL_CorrespondingItem))//if we are in a multiple mode and the currently selected element is the one we clicked, we want to unselect it. { INTERNAL_WorkaroundObservableCollectionBugWithJSIL.Remove(SelectedItems, selectorItem.INTERNAL_CorrespondingItem); removedItems.Add(selectorItem.INTERNAL_CorrespondingItem); } //else click on a new element else { SelectedItems.Add(selectorItem.INTERNAL_CorrespondingItem); addedItems.Add(selectorItem.INTERNAL_CorrespondingItem); } hasSelectionChanged = true; } //--------------------------------------------------- //Extended //--------------------------------------------------- else if (SelectionMode == SelectionMode.Extended) { int indexOfClickedItem = INTERNAL_ListsHelper.ConvertToListOfObjectsOrNull(Items).IndexOf(selectorItem.INTERNAL_CorrespondingItem); //todo-perfs: this is O(N). //if Shift is pressed if (isShift) { int indexStart = _indexOfLastClickedItemWithoutShiftKey; int indexEnd = indexOfClickedItem; int change; if (indexStart > indexEnd) { change = indexEnd; indexEnd = indexStart; indexStart = change; } int index = 0; //copy the SelectedItems in a hashset so we can easily know which items have been removed: HashSet <object> selectedItemsHashSet = CopyToHashSet(SelectedItems); //clear before adding INTERNAL_WorkaroundObservableCollectionBugWithJSIL.Clear(SelectedItems); foreach (object item in Items) { if (indexStart <= index && index <= indexEnd) { if (!INTERNAL_WorkaroundObservableCollectionBugWithJSIL.Contains(SelectedItems, item)) //todo-perfs: use a dictionary { SelectedItems.Add(item); addedItems.Add(item); if (selectedItemsHashSet.Contains(item)) { selectedItemsHashSet.Remove(item); } } } index++; } foreach (object item in selectedItemsHashSet) { removedItems.Add(item); } hasSelectionChanged = removedItems.Count > 0 || addedItems.Count > 0; } //if Control is pressed else if (isControl) { //If click on an already selected element if (INTERNAL_WorkaroundObservableCollectionBugWithJSIL.Contains(SelectedItems, selectorItem.INTERNAL_CorrespondingItem))//if we are in a multiple mode and the currently selected element is the one we clicked, we want to unselect it. { INTERNAL_WorkaroundObservableCollectionBugWithJSIL.Remove(SelectedItems, selectorItem.INTERNAL_CorrespondingItem); removedItems.Add(selectorItem.INTERNAL_CorrespondingItem); } //else click on a new element else { SelectedItems.Add(selectorItem.INTERNAL_CorrespondingItem); addedItems.Add(selectorItem.INTERNAL_CorrespondingItem); } hasSelectionChanged = true; } //Nothing is pressed else { if (SelectedItem != selectorItem.INTERNAL_CorrespondingItem) { HashSet <object> selectedItemsHashSet = CopyToHashSet(SelectedItems); INTERNAL_WorkaroundObservableCollectionBugWithJSIL.Clear(SelectedItems); SelectedItems.Add(selectorItem.INTERNAL_CorrespondingItem); addedItems.Add(selectorItem.INTERNAL_CorrespondingItem); if (selectedItemsHashSet.Contains(selectorItem.INTERNAL_CorrespondingItem)) { selectedItemsHashSet.Remove(selectorItem.INTERNAL_CorrespondingItem); } foreach (object item in selectedItemsHashSet) { removedItems.Add(item); } hasSelectionChanged = true; } } if (!isShift) { _indexOfLastClickedItemWithoutShiftKey = indexOfClickedItem; } } else { throw new NotSupportedException("SelectionMode is not Single, Multiple or Extended."); } OnSelectionChanged(new SelectionChangedEventArgs(removedItems, addedItems)); _skipSelectionChangedEvent = false; }