Jeżeli w Silverlight chcemy posortować sobie ListBox za pomocą przeciągania elementów – dosłownie mówiąc na liście mamy 10 elementów i chcemy zamienić element 1 z 6 – możemy to zrobić w bardzo prosty sposób z wykorzystaniem kontrolki ListBoxDragDropTarget dostępnej w Silverlight Toolkit. By to osiągnąć należy naszą kontrolkę ListBox opakować w ListBoxDragDropTarget, następnie ustawić ItemsPanelTemplate dla ListBox na StackPanel – jest to spowodowane tym, że ListBox używa VirtualizedStackPanel, przez co nie może on określić indeksu elementu na liście, zamiana na StackPanel załatwia problem.
Uwaga: w kodzie zakładam, że korzystamy z MVVM oraz MVVM Toolkit Light. ElementName odwołuje się nazwy kontrolki.
Kod powinien wyglądać tak:
<UserControl.Resources>
<DataTemplate x:Key="ActiveLayerListBoxItemDataTemplate" >
<StackPanel Orientation="Horizontal"
Margin="7"
HorizontalAlignment="Stretch"
ToolTipService.ToolTip="{Binding Path=Name, StringFormat='{0} Active Layer'}">
<ContentPresenter Content="{Binding Path=Icon, Mode=OneTime}"
Width="16"
Height="16"/>
<TextBlock Text="{Binding Path=Name}" />
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<!-- kod wyciety -->
<toolkit:ListBoxDragDropTarget AllowDrop="True"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch">
<i:Interaction.Triggers>
<i:EventTrigger EventName="ItemDragCompleted">
<cmd:EventToCommand Command="{Binding ElementName=ActiveLayersViewControl,
Path=DataContext.ActiveLayersReOrderedCommand, Mode=OneWay}"
CommandParameter="{Binding .}" />
<!--<ia:CallMethodAction MethodName="ReorderList" TargetObject="{Binding}" />-->
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox x:Name="SelectedLayersListBox"
ItemsSource="{Binding Path=SelectedLayers, Mode=TwoWay}"
ItemTemplate="{StaticResource ActiveLayerListBoxItemDataTemplate}"
SelectionMode="Extended" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</toolkit:ListBoxDragDropTarget>
Teraz by dobrać się do posortowanych elementów, musimy wykonać jeszcze jedną dodatkową czynność. Obsłużyć zdarzenie ItemDragCompleted – kiedy ono zachodzi, możemy bezproblemowo odwołać się do naszej listy i sprawdzić kolejność/wysłać wiadomość o zaistniałym fakcie/zapisać zmiany:
// RelayCommand i Messenger pochodza z MVVM Toolkit Light
public RelayCommand ActiveLayersReOrderedCommand { get; private set; }
// ...
ActiveLayersReOrderedCommand = new RelayCommand(() =>
Messenger.Default.Send(new LayersOrderChangedMessage(SelectedLayers.Select(x => x.Id).ToList()))
);














