This is a migrated thread and some comments may be shown as answers.

Programmatically selecting items does not work in sync with manually selecting

3 Answers 152 Views
ListBox
This is a migrated thread and some comments may be shown as answers.
Peter
Top achievements
Rank 1
Peter asked on 06 Sep 2013, 01:14 PM
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):
  1. Select item 15
  2. Press button 'First item'
  3. Extend the selection to item 3 by holding the shift-button and clicking on item 3
  4. result: instead of selecting items 1-3, you will have items 3-15 selected

<UserControl x:Class="SelectedItemsRadListBox.MainPage"
    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; } }
    }
}

3 Answers, 1 is accepted

Sort by
0
Polya
Telerik team
answered on 11 Sep 2013, 01:29 PM
Hi Peter,

Thank you for contacting us and pointing this problem. It is now logged in our PITS, you can track its progress here.

The problem is that when RadListBox SelectedItem is changed the behavior (extended, multiple)  the Anchor of the selection is not changed. As a workaround I am sending you a sample project using your code that has a modified ExtendedBehavior class, called CustomExtendedBehavior. In the GetItemsForSelection method I included the following code:
if (itemsForSelection.Count == 1)
{
    selectionState.Anchor = itemsForSelection[0];
}

With this code I am setting the Anchor to the specified ( first, middle, last ) item. Modify this in a way that suits your needs. Also I removed the SelectionRadListBoxBehavior as setting the SelectionMode="Extended" triggers the same functionality. In the ViewModel I included the SelectedObject property that I bind the RadListBox SelectedItem to.

Hopefully this helps. After we fix this issue you will no longer need the CustomExtendedBehavior.

I've updated your Telerik Points as a small sign of our appreciation for your efforts. 

Regards,
Polya
Telerik
TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for SILVERLIGHT.
Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
Sign up for Free application insights >>
0
Peter
Top achievements
Rank 1
answered on 11 Sep 2013, 01:56 PM
Hi Polya,

Thank you for the answer, but we are working with telerik version 2012.1.215.1050.
Is there a work around for the problem for this version?

Regards,
Peter
0
Polya
Telerik team
answered on 16 Sep 2013, 12:32 PM
Hi Peter,

Unfortunately version 2012.1.215.1050 of Telerik controls is too old for this kind of workaround.
The solution I proposed is valid with the newer versions, so you may consider upgrading.

We're sorry for any inconvenience caused.

Regards,
Polya
Telerik
TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for SILVERLIGHT.
Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
Sign up for Free application insights >>
Tags
ListBox
Asked by
Peter
Top achievements
Rank 1
Answers by
Polya
Telerik team
Peter
Top achievements
Rank 1
Share this question
or