I have UserControls which i have in a ListBox, which then hosts them on a Canvas. I've then made the UserControls draggable on the canvas by using the DraggableExtender(Dragging an image in WPF).
But ever since I changed from ItemsControl to ListBox, to be able to make the controls selectable, the Dragging works really bad. For instance if I'm dragging a control over another control the other control gets focused and sticks to the dragging. Also if I move the mouse outside the canvas the usercontrol gets stuck at the edge and i loose dragging focus, like if CaptureMouse doesn't work.
The ListBox looks like this(when it worked before it was an ItemsControl):
<ListBox ItemsSource="{Binding Components}" SelectedItem="{Binding SelectedItem}" Background="Transparent">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas ClipToBounds="True" Height="{Binding CurrentProject.Height, Converter={StaticResource SizeConverter}}"
Width="{Binding CurrentProject.Width, Converter={StaticResource SizeConverter}}"
HorizontalAlignment="Left" VerticalAlignment="Top">
<Canvas.Background>
<SolidColorBrush Color="{DynamicResource {x:Static SystemColors.WindowFrameColorKey}}"/>
</Canvas.Background>
</Canvas>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid>
<Border Background="{TemplateBinding Background}" />
<ContentPresenter/>
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True" />
<Condition Property="IsSelected" Value="False"/>
</MultiTrigger.Conditions>
<Setter Property="Background" Value="#8868D5FD" />
</MultiTrigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="#4468D5FD" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Utils:DraggableExtender.CanDrag" Value="True" />
<Setter Property="Canvas.Top" Value="{Binding Path=Conveyor.Y, Converter={StaticResource SizeConverter},Mode=TwoWay}" />
<Setter Property="Canvas.Left" Value="{Binding Path=Conveyor.X, Converter={StaticResource SizeConverter},Mode=TwoWay}" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
My DraggableExtender looks like this:
public class DraggableExtender : DependencyObject
{
public static readonly DependencyProperty CanDragProperty =
DependencyProperty.RegisterAttached("CanDrag", typeof(bool), typeof(DraggableExtender),
new UIPropertyMetadata(false, OnChangeCanDragProperty));
private static bool isDragging = false;
private static Point offset;
public static void SetCanDrag(UIElement element, bool o)
{
element.SetValue(CanDragProperty, o);
}
public static bool GetCanDrag(UIElement element, bool o)
{
return (bool)element.GetValue(CanDragProperty);
}
private static void OnChangeCanDragProperty(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
UIElement element = d as UIElement;
if (element == null) return;
if (e.NewValue != e.OldValue)
{
if ((bool)e.NewValue)
{
element.PreviewMouseDown += element_PreviewMouseDown;
element.PreviewMouseUp += element_PreviewMouseUp;
element.PreviewMouseMove += element_PreviewMouseMove;
}
else
{
element.PreviewMouseDown -= element_PreviewMouseDown;
element.PreviewMouseUp -= element_PreviewMouseUp;
element.PreviewMouseMove -= element_PreviewMouseMove;
}
}
}
private static void element_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
FrameworkElement element = sender as FrameworkElement;
if (element == null) return;
Debug.WriteLine(element);
isDragging = true;
element.CaptureMouse();
offset = e.GetPosition(element);
}
private static void element_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (!isDragging) return;
FrameworkElement element = sender as FrameworkElement;
if (element == null) return;
Canvas canvas = element.FindAncestor<Canvas>();
if (canvas == null) return;
Point mousePoint = e.GetPosition(canvas);
mousePoint.Offset(-offset.X, -offset.Y);
element.SetValue(Canvas.LeftProperty, mousePoint.X);
element.SetValue(Canvas.TopProperty, mousePoint.Y);
}
private static void element_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
FrameworkElement element = sender as FrameworkElement;
if (element == null) return;
element.ReleaseMouseCapture();
isDragging = false;
}
}
I've been trying to find a solution but so far I've been unsuccessful. Does anyone have any idea why this is happening and how I can solve it?