[英]C# WPF Draggable UserControls in ListBox on Canvas
我在ListBox中有UserControl,然后將它們托管在Canvas上。 然后,我通過使用DraggableExtender( 在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;
}
}
我一直在尋找解決方案,但到目前為止,我一直沒有成功。 有誰知道為什么會這樣以及我如何解決呢?
我終於能夠弄清楚如何解決這個問題,或者至少如何解決。 問題似乎在於ListBox還在其選擇代碼中捕獲了鼠標。 所以我更改的是添加e.Handled = true,以便ListBox不會獲取事件並因此覆蓋mousecapture。 這確實使選擇機制無法使用,但是要解決此問題,我將代碼移到僅偵聽MouseRight事件,這意味着當我單擊鼠標左鍵時,我選擇了鼠標,當我單擊鼠標右鍵時,可以拖動。
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);
e.Handled = true;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.