This question is locked. New answers and comments are not allowed.
Hello,
I have an issue with selecting items in a RadListBox.
I have initially a selected item (programmatically), when i want to extend that selection manually (shift-key) i get completely different items selected. If I could get a work around for this problem, it would be great.
It seems to me that the UI-selection never gets cleared (which i clearly do in code) and when i extend the selection it uses the 'non-cleared' selected item instead of the real selected item.
One example case where it goes wrong (using the supplied code below):
I have an issue with selecting items in a RadListBox.
I have initially a selected item (programmatically), when i want to extend that selection manually (shift-key) i get completely different items selected. If I could get a work around for this problem, it would be great.
It seems to me that the UI-selection never gets cleared (which i clearly do in code) and when i extend the selection it uses the 'non-cleared' selected item instead of the real selected item.
One example case where it goes wrong (using the supplied code below):
- Select item 15
- Press button 'First item'
- Extend the selection to item 3 by holding the shift-button and clicking on item 3
- result: instead of selecting items 1-3, you will have items 3-15 selected
<UserControl x:Class="SelectedItemsRadListBox.MainPage" xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation" xmlns:SelectedItemsRadListBox="clr-namespace:SelectedItemsRadListBox" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <UserControl.Resources> <SelectedItemsRadListBox:ViewModel x:Key="ViewModel" /> <DataTemplate x:Key="template" DataType="SelectedItemsRadListBox:TestObject"> <Grid> <Border BorderThickness="0,0,1,0" BorderBrush="Black" Padding="5,0,5,0" VerticalAlignment="Center" HorizontalAlignment="Right"> <TextBlock FontSize="10" Text="{Binding Path=Index}" /> </Border> </Grid> </DataTemplate> </UserControl.Resources> <Grid DataContext="{StaticResource ViewModel}" x:Name="LayoutRoot" Background="White"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="124*" /> <RowDefinition Height="176*" /> </Grid.RowDefinitions> <telerik:RadButton Content="First item" Command="{Binding Path=First}" /> <telerik:RadButton Content="Middle item" Grid.Column="1" Command="{Binding Path=Middle}" /> <telerik:RadButton Content="Last item" Grid.Column="2" Command="{Binding Path=Last}" /> <telerik:RadListBox Grid.Row="1" Grid.ColumnSpan="3" Margin="5,10,5,0" ItemsSource="{Binding Path=TestObjects}" SelectionMode="Extended" ItemTemplate="{StaticResource template}"> <i:Interaction.Behaviors> <SelectedItemsRadListBox:SelectionRadListBoxBehavior SelectedItems="{Binding Path=SelectedTestObjects, Mode=TwoWay}" /> </i:Interaction.Behaviors> </telerik:RadListBox> </Grid></UserControl>using System;using System.Collections;using System.Collections.ObjectModel;using System.Collections.Specialized;using System.Linq;using System.Windows;using System.Windows.Interactivity;using Telerik.Windows.Controls;namespace SelectedItemsRadListBox{ public class SelectionRadListBoxBehavior : Behavior<RadListBox> { #region SelectedItems (ObservableCollection<TestObject>) public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.Register("SelectedItems", typeof(ObservableCollection<TestObject>), typeof(SelectionRadListBoxBehavior), new PropertyMetadata(default(ObservableCollection<TestObject>), OnSelectedItemsPropertyChanged)); private static void OnSelectedItemsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var selectionRadListBoxBehavior = d as SelectionRadListBoxBehavior; if (selectionRadListBoxBehavior == null) return; var oldCollection = e.OldValue as ObservableCollection<TestObject>; if (oldCollection != null) oldCollection.CollectionChanged -= selectionRadListBoxBehavior.SelectedItemsCollectionChanged; var newCollection = e.NewValue as ObservableCollection<TestObject>; if (newCollection != null) newCollection.CollectionChanged += selectionRadListBoxBehavior.SelectedItemsCollectionChanged; } private bool _isCollectionUpdateDisabled; private void SelectedItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { if (_isCollectionUpdateDisabled) return; try { _isListBoxUpdateDisabled = true; switch (e.Action) { case NotifyCollectionChangedAction.Add: case NotifyCollectionChangedAction.Remove: var newSelectedItems = (IList)sender; AssociatedObject.SelectedItems.Clear(); AssociatedObject.SelectItems(newSelectedItems); if (newSelectedItems.Count > 0) AssociatedObject.ScrollIntoView(AssociatedObject.Items.IndexOf(newSelectedItems[0])); break; case NotifyCollectionChangedAction.Replace: break; case NotifyCollectionChangedAction.Reset: AssociatedObject.SelectedItems.Clear(); break; default: throw new ArgumentOutOfRangeException(); } } finally { _isListBoxUpdateDisabled = false; } } public ObservableCollection<TestObject> SelectedItems { get { return (ObservableCollection<TestObject>)GetValue(SelectedItemsProperty); } set { SetValue(SelectedItemsProperty, value); } } #endregion private bool _isListBoxUpdateDisabled; private void AssociatedObjectSelectionChanged(object sender, SelectionChangedEventArgs e) { if (_isListBoxUpdateDisabled) return; try { _isCollectionUpdateDisabled = true; SelectedItems.Clear(); var selectedItems = AssociatedObject.SelectedItems.OfType<TestObject>(); foreach (var selectedItem in selectedItems) SelectedItems.Add(selectedItem); } finally { _isCollectionUpdateDisabled = false; } } #region Overrides of Behavior protected override void OnAttached() { base.OnAttached(); if (SelectedItems == null) SelectedItems = new ObservableCollection<TestObject>(); AssociatedObject.SelectionChanged += AssociatedObjectSelectionChanged; } protected override void OnDetaching() { AssociatedObject.SelectionChanged -= AssociatedObjectSelectionChanged; base.OnDetaching(); } #endregion }}using System.Collections.ObjectModel;using System.Linq;using System.Windows.Input;using Telerik.Windows.Controls;namespace SelectedItemsRadListBox{ public class ViewModel : ViewModelBase { #region property SelectedTestObjects private readonly ObservableCollection<TestObject> _selectedTestObjects = new ObservableCollection<TestObject>(); public ObservableCollection<TestObject> SelectedTestObjects { get { return _selectedTestObjects; } } #endregion property SelectedTestObjects #region property TestObjects private readonly ObservableCollection<TestObject> _testObjects = new ObservableCollection<TestObject>(); public ObservableCollection<TestObject> TestObjects { get { return _testObjects; } } #endregion property TestObjects #region Commands public ICommand First { get; set; } public ICommand Middle { get; set; } public ICommand Last { get; set; } private void InitCommands() { First = new DelegateCommand(o => OnFirst()); Middle = new DelegateCommand(o => OnMiddle()); Last = new DelegateCommand(o => OnLast()); } #endregion public ViewModel() { InitCommands(); for (int i = 0; i < 20; i++) { TestObjects.Add(new TestObject(i)); } } #region Command handlers private void OnFirst() { SelectedTestObjects.Clear(); SelectedTestObjects.Add(TestObjects.First()); } private void OnMiddle() { SelectedTestObjects.Clear(); SelectedTestObjects.Add(TestObjects[TestObjects.Count / 2]); } private void OnLast() { SelectedTestObjects.Clear(); SelectedTestObjects.Add(TestObjects.Last()); } #endregion }}namespace SelectedItemsRadListBox{ public class TestObject { private readonly int _index; public TestObject(int index) { _index = index; } public int Index { get { return _index; } } }}