簡體   English   中英

C#WPF在畫布上的列表框中的可拖動用戶控件

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM