如何制作更精确的滑块控件?

时间:2017-05-27 11:02:48

标签: c# wpf user-interface user-controls precision

我想制作一个滑块控件,当我按下一个键(让我们说移位)时,它的拇指(及其值)将比鼠标拖动得慢,因此变得更加精确。

我还是WPF的新手,我真的不知道从哪里开始。

任何提示?

EDIT ---

到目前为止,我正在尝试使用水平滑块:

    Point pStart;
    Point pCurrent;

    private void CMiXSlider_DragDelta(object sender, DragDeltaEventArgs e)
    {
        if (Keyboard.IsKeyDown(Key.LeftShift))
        {
            pCurrent = Mouse.GetPosition(CMiXSlider);
            double center = Math.Abs(pCurrent.X - pStart.X);
            Value = (1.0 / CMiXSlider.ActualWidth) * center;
        }
    }

    private void CMiXSlider_DragStarted(object sender, DragStartedEventArgs e)
    {
            pStart = Mouse.GetPosition(CMiXSlider);
    }

它的行为几乎与预期相同,但拇指始终位于0和pCurrent之间的中心位置。看起来,当DragDelta被触发时,pStart不会保留其值。

2 个答案:

答案 0 :(得分:2)

这主要是一个用户体验问题,其次只是一个WPF问题。我无法帮助你使用WPF,但我可以从UX的角度给你一些输入。

<强> 别。

不要这样做。这是一个坏主意,原因有很多:

a)非常不标准。我听过的任何应用程序都没有这样的东西。因此,当按下某个修改键时,没有人会知道滑块的行为会有所不同,并且没有人会尝试使用修改键向下拖动滑块。

b)你不能教用户这样做。使用包含如何使用它的说明的其他文本标签来混乱您的用户界面是笨拙的,并且在几十年前被废弃了。

c)即使你以某种方式设法教导用户这样做,学习使用现有和熟悉的控件的一些新方法的心理努力不值得额外的好处,只需更好地控制滑块的精度

d)这可以通过将滑块移动指针移动距离的一小部分,或者通过减慢指针的速度来实现。

  • 将滑块移动指针移动距离的一小部分看起来很丑陋。它会起作用,但看起来会破碎。

  • 减慢指针是一个棘手的命题,它只适用于鼠标。用户使用手指的触摸界面怎么样?你不能放慢速度。

解决方案:

  1. 通过箭头键实现移动。这是允许精确控制滑块值的标准方法。当滑块具有焦点时,箭头键应将值更改为一个单位。

  2. 如果应用程序的性质非常重要,那么请考虑使用数字控件替换滑块。如果需要,使它成为一个微调器。 (带有向上和向下按钮的数字控件。)或者可能使其成为带有下拉滑块的数字控件,因此主要的操作方式是数字,滑块操作是辅助和可选的。 (我不知道如何用WPF做到这一点。)

答案 1 :(得分:0)

有时此功能很有用,例如照明/音频控制或机械臂的精确定位。在这些UX情况下,用户可能会通过RTFM找到答案。

我不在PC前面,这里有一些简单的伪代码,用于说明如何使用自定义滑块控件来执行此操作,该控件在Shift键关闭时忽略每一秒的值更改。

return View("MyView");

您可以将此解决方案应用于数字上/下,滚动条和各种其他控件。

除了上面的代码之外,为了进行更精确的交互,您可以在OnValueChanged事件中检测Ctrl键并提高精度,例如

public class CustomSlider : Slider 
{ 
  private int precision = 2;
  private int movement = 0;
  protected override void OnValueChanged(double oldValue, double newValue) 
  {
    bool keyShift = (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)) 

    if (keyShift && movement % precision == 0)
    {
      base.OnValueChanged(oldValue, newValue); 
    }
    else if (!keyShift)
    {
      base.OnValueChanged(oldValue, newValue); 
    }

    movement++;
    if (movement == int.MaxValue) movement = 0;
 }
}