PanelDragDropTarget и ListBoxDragDropTarget: что именно перетаскивается?

Приложение My Silverlight 4 позволяет перетаскивать из ListBoxDragDropTarget в PanelDragDropTarget.

В приложении есть Person объекты, которые представляют собой модели, представляющие людей, и PersonControl пользовательские элементы управления, имеющие Person в качестве контекста данных.

Для справки соответствующий код:

<toolkit:ListBoxDragDropTarget x:Name="dtListBox" Grid.Row="2" AllowedSourceEffects="Copy" AllowDrop="True" 
                               HorizontalContentAlignment="Stretch" 
                               VerticalAlignment="Top" VerticalContentAlignment="Stretch">
         <!-- FilteredMembers is of type ObservableCollection<Person> -->
    <ListBox ItemsSource="{Binding FilteredMembers}" 
                               MinWidth="42"
                               MinHeight="42">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <my:PersonControl />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
</toolkit:ListBoxDragDropTarget>

и

<toolkit:PanelDragDropTarget AllowDrop="True" AllowedSourceEffects="Copy,Move" 
              Drop="PanelDragDropTarget_Current_Drop">
    <StackPanel>
        <ctl:PersonControl Margin="3,3,3,3" x:Name="pcCurrent"></ctl:PersonControl>
    </StackPanel>
</toolkit:PanelDragDropTarget>

Все идет нормально. Когда я перетаскиваю на PanelDragDropTarget, я получаю Person.

Однако я также разрешаю перетаскивать из PanelDragDropTarget в другой PanelDragDropTarget. В этом случае, а не Person, отброшенный объект будет PersonControl.

Таким образом, отброшенный объект может быть либо Person, либо PersonControl в зависимости от того, откуда он появился.

Я действительно хочу перетаскивать Person объекты во всех случаях, а не перемещать PersonControl. Как я могу изменить свой PanelDragDropTarget так, чтобы при перетаскивании тянулось Person, а не PersonControl?

Я рассмотрел этот очень похожий вопрос:

Перетащите / отпустите из ListBoxDragDropTarget в PanelDragDropTarget

но не понимаю, как это решает проблему.


person Eric J.    schedule 06.09.2011    source источник


Ответы (1)


Вы совершенно правы относительно разницы между способами передачи удаленных объектов PanelDragDropTargets и ListBoxDragDropTargets. При перетаскивании между двумя объектами ListBoxDragDropTarget вы переносите часть данных, которая привязана к элементу управления, тогда как перетаскивание между двумя объектами PanelDragDropTargets передает «захваченный» элемент UIElement.

Лучший способ, который я нашел, - это унаследовать новый класс от PanelDragDropTarget, который ожидает, что на него будет сброшен фрагмент данных вместо UIElement. Новый класс хранит объект данных в DataContext класса / элемента управления. Это позволяет коду, похожему на ваш, работать.

Класс:

public class ElementDragDropTarget : PanelDragDropTarget
{
    protected override bool CanAddItem(Panel itemsControl, object data)
    {
        return true;
    }

    protected override void InsertItem(Panel itemsControl, int index, object data)
    {
        itemsControl.DataContext = data;
    }

    protected override bool CanRemove(Panel itemsControl)
    {
        return true;
    }

    protected override void RemoveItem(Panel itemsControl, object data)
    {
        itemsControl.DataContext = null;
    }

    protected override void RemoveItemAtIndex(Panel itemsControl, int index)
    {
        itemsControl.DataContext = null;
    }

    protected override object ItemFromContainer(Panel itemsControl, UIElement itemContainer)
    {
        return itemsControl.DataContext;
    }
}

Изменения в вашем коде:

<local:ElementDragDropTarget AllowDrop="True" AllowedSourceEffects="Copy,Move" Drop="PanelDragDropTarget_Current_Drop">
    <Grid>
        <ctl:PersonControl Margin="3,3,3,3" x:Name="pcCurrent"></ctl:PersonControl>
    </Grid>
</local:ElementDragDropTarget >

Я понимаю, что это решение позволяет перетаскивать только один элемент в ElementDragDropTarget. Я предполагаю, что это то, что вы хотите сделать, потому что, если вы хотите поместить в него несколько объектов данных, вам, вероятно, следует просто использовать другой ListBoxDragDropTarget (тем более, что вы просто используете StackPanel).

person YeahStu    schedule 01.12.2011