AllDropTargetsValid=False and DropTargets

Sep 28, 2009 at 1:45 AM

G'day Kevin,

Thanks for the very easy to use controls that you have developed.  Good luck in the Silverlight comp - if it was upto me your module would be the winner. :)

I using your module in a prototype application to make sure that it would do what we need it to do.  So far it has been impressive but there is one thing that I cannot get working.  I'm trying to limit a DragSource to a particular DropTarget.  I'm setting the AllDropTargetsValid=False and the DropTargets on the DragSource (see code below), but I receive an unhandle exception when the DragSource is being created.

So here's what I want to get working.  My data structure looks like this: 1-n Locations and each Location can have 1-n Motor sections.  What I want to be able to do is move a Motor section from one Location to another.  The screen is laid out with the Locations stored in a ListBox when the user selects a Location a list of Motor sections is displayed next to the Locations.  I want to be able to grab a Motor section and drop it onto a Location within the ListBox, thus allowing me to move the Motor section in the code behind.

Here is my xaml:

                <!--
Locations
-->
<TextBlock Text="Locations:" FontSize="12" /> <ListBox x:Name="Locations" Background="Transparent" SelectionChanged="Locations_SelectionChanged"> <ListBox.ItemTemplate> <DataTemplate>

<dragdrop:DropTarget DropBorderBrush="SlateBlue"
x:Name="DropTargetLocation"
DragSourceDropped="DropTargetLocation_DragSourceDropped">
<dragdrop:DropTarget.Content>
<dragdrop:DragSource DraggingEnabled="False" Background="Transparent"> <Border Width="Auto"
Height="Auto"
CornerRadius="10"
BorderBrush="DodgerBlue"
Background="Transparent" BorderThickness="3" > <StackPanel> <Border Width="100" Height="Auto" Background="DodgerBlue" > <TextBlock Text="Location" FontSize="15" Foreground="White" Margin="10,0,0,0"/> </Border> <StackPanel Orientation="Horizontal" > <Image Source="Images/Location.png"
Height="50"
Width="50" Margin="3,3,3,3"/> <TextBlock Text="{Binding Text}" Margin="3,3,3,3"/> </StackPanel> </StackPanel> </Border> </dragdrop:DragSource> </dragdrop:DropTarget.Content> </dragdrop:DropTarget> </DataTemplate> </ListBox.ItemTemplate> </ListBox>
                <!--
                Motor
                -->
                <TextBlock Text="Motors:" FontSize="12" />
                <ListBox x:Name="Motors" Background="Transparent" >
                    <ListBox.ItemTemplate>
                        <DataTemplate>

                            <Border Width="Auto" Height="Auto" CornerRadius="10" BorderBrush="DodgerBlue" BorderThickness="3" >
                                <StackPanel>
                                    <Border Width="100" Height="Auto" Background="DodgerBlue" >
                                        <TextBlock Text="Motor" FontSize="15" Foreground="White" Margin="10,0,0,0" Width="Auto"/>
                                    </Border>
                                    <StackPanel Orientation="Horizontal" >
                                        <dragdrop:DragSource AllDropTargetsValid="False"
                                                             DropTargets="DropTargetLocation"
                                                             ShowReturnToOriginalPositionAnimation="False"
                                                             DropMode="ReturnDragSource"
                                                             DragHandleMode="FullDragSource"
                                                             Tag="Motor"
                                                             Background="Transparent">
                                            <Image Source="Images/Motor.png" 
                                                   Height="50" 
                                                   Width="50"
                                                   Margin="3,3,3,3"/>

                                            <dragdrop:DragSource.Ghost>
                                                <Image Source="Images/Motor.png" 
                                                       Height="50" 
                                                       Width="50"
                                                       Margin="3,3,3,3"
                                                       Opacity="0.5"/>

                                            </dragdrop:DragSource.Ghost>
                                        </dragdrop:DragSource>
                                        <TextBlock Text="{Binding Text}" Margin="3,3,3,3"/>
                                    </StackPanel>
                                </StackPanel>
                            </Border>

                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>

In the xaml above you can see the I have set the DragSource's DropTargets attribute to "DropTargetLocation" which is the x:Name of my DragSource.  Unfortunately when I do this I get an unhandled expection when I click on the Location ListBox which is when the Motor sections are drawn and the DragSources are created.

Any help would be much appricated.

Regards

Maca

Sep 28, 2009 at 6:25 AM

Kevin,

I found a solution but I'm hoping that there is a easier way. :)

This is what I did.

I started by simplying the problem.  I created a single drop target and a single drag source.  In the loaded event I implemented this code:

 

void MainPage_Loaded(object sender, RoutedEventArgs e)
{   
   myDragSource.DropTargets = new List<DropTarget>();
   myDragSource.DropTargets.Add(myDropTarget);
}

 

This worked so basically I had to initialise the DragTargets list and then manually add my DropTarget to the list.

Using this I now had to implemented the same thing but with 2 listbox controls (back to my original problem).  This was more difficult as I found it hard to access the controls within the listbox templete.  Below is how I resolved.

Firstly I created a list of DropTargets that I can use later when the DragSources are moved.

 

List<DropTarget> dropTargets = new List<DropTarget>();

 

I then created a event for the DropTarget Loaded and in this event I add the Drop Targets as they get created.

 

        private void DropTargetLocation_Loaded(object sender, RoutedEventArgs e)
        {
            DropTarget dt = sender as DropTarget;
            dropTargets.Add(dt);

        }

 

I also needed to clear out the list of drop targets just before I bind my ItemsSource for the listbox:

 

dropTargets.Clear();

 

I then created a Loaded event handler for the DragSource and in this method I add all the DropTargets in my list (dropTargets) into the DropTargets list of the DragSource.

 

        private void DragSourceMotor_Loaded(object sender, DragEventArgs args)
{
DragSource ds = sender as DragSource;

if (ds.DropTargets == null)
{
ds.DropTargets = new List<DropTarget>();
}

foreach (DropTarget dt in dropTargets)
{
ds.DropTargets.Add(dt);
}
}

 

This works but it is a lot of work.

Anyway, its a solution but it would be good if there was a better way.

Cheers Maca