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()))
);