【发布时间】:2011-07-29 22:38:33
【问题描述】:
我有一个列表框中的用户控件,然后将它们托管在画布上。然后,我使用 DraggableExtender(Dragging an image in WPF) 使 UserControls 在画布上可拖动。
但是自从我从 ItemsControl 更改为 ListBox 之后,为了能够使控件可选择,Dragging 的工作真的很糟糕。例如,如果我将一个控件拖动到另一个控件上,则另一个控件将获得焦点并坚持拖动。此外,如果我将鼠标移到画布外,用户控件会卡在边缘并且我失去了拖动焦点,就像 CaptureMouse 不起作用一样。
ListBox 看起来像这样(当它在成为 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>
我的 DraggableExtender 看起来像这样:
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;
}
}
我一直在努力寻找解决方案,但到目前为止我没有成功。有谁知道为什么会发生这种情况以及我该如何解决?
【问题讨论】:
标签: c# wpf canvas listbox draggable