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; } }
}
}