WPF自定义控件单击和拖动/跟随鼠标指针

本文关键字:跟随 鼠标指针 拖动 自定义控件 单击 WPF | 更新日期: 2023-09-27 18:19:25

我已经阅读了这个问题的各种解决方案,现在我想知道在哪种情况下(尤其是我的情况下)哪一个是首选

我已经创建了一个自定义控件,在画布的中间渲染一个色轮和一个圆圈(Ellipse)。现在我想把这个圆圈作为色轮上的选择器来点击和拖动

可能的解决方案包括:覆盖OnClick和/或OnMouseMove事件,并通过依赖属性或使用TemplateParts甚至在控件代码后面生成圆圈来更新圆圈的位置。

我想知道是否也有可能在XAML中使用触发器来实现这种效果,以及哪种解决方案将提供"最平滑"的运动。

更新1:为了处理注释,这里有一些代码:

ColorPicker.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:TrigDebugUtil.Controls">

    <Style x:Key="ColorPicker" TargetType="{x:Type local:ColorPicker}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:ColorPicker}">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                        <Grid>
                            <Image Source="{TemplateBinding ColorWheelImage}" Width="500" Height="500"/>
                            <Canvas Width="10" Height="10" HorizontalAlignment="Center" VerticalAlignment="Center">
                                <Ellipse Fill="{TemplateBinding Property=SelectedColor}" Width="10" Height="10" Stroke="Black" StrokeThickness=".5" />
                            </Canvas>
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

ColorPicker.cs

namespace TrigDebugUtil.Controls
{
    public class ColorPicker : Control
    {
        #region Private Fields
        #endregion //Private Fields
        #region Dependency Properties
        public static readonly DependencyProperty ColorWheelImageProperty = DependencyProperty.Register("ColorWheelImage", typeof(WriteableBitmap), typeof(ColorPicker));
        public static readonly DependencyProperty SelectedColorProperty = DependencyProperty.Register("SelectedColor", typeof(SolidColorBrush), typeof(ColorPicker));
        #endregion //Dependency Properties
        #region Properties
        public WriteableBitmap ColorWheelImage
        {
            get { return (WriteableBitmap)GetValue(ColorWheelImageProperty); }
            private set { SetValue(ColorWheelImageProperty, value);  }
        }
        public SolidColorBrush SelectedColor
        {
            get { return (SolidColorBrush)GetValue(SelectedColorProperty); }
            private set { SetValue(SelectedColorProperty, value); }
        }
        #endregion //Properties
        static ColorPicker()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorPicker), new FrameworkPropertyMetadata(typeof(ColorPicker)));
        }
        public ColorPicker()
        {
            ColorWheelImage = new WriteableBitmap(500, 500, 96, 96, PixelFormats.Rgb24, null);
            SelectedColor = Brushes.White;
        }
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            Byte[] pixels = new Byte[1500 * 500];
            // Update algo here

            ColorWheelImage.WritePixels(new Int32Rect(0, 0, 500, 500), pixels, 1500, 0);
        }
    }
}

我希望能够点击画布上的椭圆并将其移动到控件本身的另一个位置(即在图像上)

WPF自定义控件单击和拖动/跟随鼠标指针

对于有相同问题的人,一个可能的解决方案是将可拖动对象实现为Thumb并覆盖其DragStarted DragDeltaDragCompleted事件。

下面是一个例子:

    private void OnThumbDragDelta(object sender, DragDeltaEventArgs e)
    {
        Thumb thumb = sender as Thumb;
        double newX = Canvas.GetLeft(thumb) + e.HorizontalChange;
        double newY = Canvas.GetTop(thumb) + e.VerticalChange;
            Canvas.SetLeft(thumb, newX);
            Canvas.SetTop(thumb, newY);

        // This is optional for routed events.
        e.RoutedEvent = ThumbDragDeltaEvent;
        RaiseEvent(e);
    }

不使用DragStartedDragCompleted事件

我想看看这是否是一个首选的解决方案,或者它是否有任何缺点的评论。在我看来,这不是最有效的,在鼠标快速移动时,拇指的移动是延迟的而且并不总是"在鼠标的右边"