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

时间:2014-08-24 21:55:54

标签: c# wpf xaml events drag-and-drop

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

我创建了一个自定义控件,用于在中间的画布上渲染色轮和圆圈(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);

        }
    }
}

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

1 个答案:

答案 0 :(得分:0)

对于遇到相同问题的人,一种可能的解决方案是将可拖动对象实现为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事件。

我希望看到关于这是一个首选解决方案的评论,或者它是否有任何缺点。从我所看到的不是最有效的,在快速鼠标移动时,拇指运动被延迟而不是总是“在鼠标下”