2017-05-30 2 views
-1

私は、これは可能な限り最高のUXではありません知っているが、それでも、私はこれを達成したいですしたがってそのValue)は通常通り2倍遅く移動します。ファインpositionningのスライダーサム

これはこれまで私が行ってきたことです。

public partial class CustomSlider : UserControl 
{ 
    public CustomSlider() 
    { 
     InitializeComponent(); 

     CMiXSlider.ApplyTemplate(); 
     Thumb thumb0 = (CMiXSlider.Template.FindName("PART_Track", CMiXSlider) as Track).Thumb; 
     thumb0.MouseEnter += new MouseEventHandler(thumb_MouseEnter); 

    } 

    private void thumb_MouseEnter(object sender, MouseEventArgs e) 
    { 
     if (e.LeftButton == MouseButtonState.Pressed && e.MouseDevice.Captured == null) 
     { 
      MouseButtonEventArgs args = new MouseButtonEventArgs(e.MouseDevice, e.Timestamp, MouseButton.Left); 
      args.RoutedEvent = MouseLeftButtonDownEvent; 
      (sender as Thumb).RaiseEvent(args); 
     } 
    } 

    Point pStart; 
    Point pCurrent; 
    Point pCenter; 
    bool isDragging; 

    private void CMiXSlider_DragStarted(object sender, DragStartedEventArgs e) 
    { 
     isDragging = true; 
     if (Keyboard.IsKeyDown(Key.LeftShift)) 
     { 
      pStart = Mouse.GetPosition(CMiXSlider); 
     } 
    } 

    private void CMiXSlider_DragDelta(object sender, DragDeltaEventArgs e) 
    { 
     pCurrent = Mouse.GetPosition(CMiXSlider); 
     if (Keyboard.IsKeyDown(Key.LeftShift) == true) 
     { 
      pCenter.X = Math.Abs(pCurrent.X - pStart.X); 
      pCenter.Y = Math.Abs(pCurrent.Y - pStart.Y); 
      Value = (1.0/CMiXSlider.ActualWidth) * pCenter.X/2 + (1.0/CMiXSlider.ActualWidth)*pStart.X; 
      if (Value >= 1.0) 
      { 
       Value = 1.0; 
      } 
      else if (Value <= 0.0) 
      { 
       Value = 0.0; 
      } 
     } 
    } 

    private void CMiXSlider_DragCompleted(object sender, DragCompletedEventArgs e) 
    { 
     isDragging = false; 
    } 

    private void CMiXSlider_KeyDown(object sender, KeyEventArgs e) 
    { 

     if (Keyboard.IsKeyDown(Key.LeftShift) && isDragging == true) 
     { 
      pStart = Mouse.GetPosition(CMiXSlider); 
     } 
    } 

とXAML:しかし

<UserControl x:Class="CMiX.CustomSlider" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:local="clr-namespace:CMiX" 
     mc:Ignorable="d" 
     d:DesignHeight="116.3" d:DesignWidth="567.2"> 
<UserControl.Resources> 
    <ResourceDictionary> 
     <ResourceDictionary.MergedDictionaries> 
      <ResourceDictionary Source="/CMiX_UserControl;component/RessourceDictionnaries/Brushes/GenericBrushes.xaml"/> 
      <ResourceDictionary Source="/CMiX_UserControl;component/RessourceDictionnaries/Styles/BaseSliderStyle.xaml"/> 
     </ResourceDictionary.MergedDictionaries> 
    </ResourceDictionary> 
</UserControl.Resources> 
<Slider x:Name="CMiXSlider" Style="{StaticResource BaseSliderStyle}" Margin="1" 
     Thumb.DragDelta="CMiXSlider_DragDelta" 
     Thumb.DragStarted="CMiXSlider_DragStarted" 
      Orientation="{Binding Orientation, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type local:CustomSlider}}}" 
      Value="{Binding Value, Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type local:CustomSlider}}}" 
      IsMoveToPointEnabled="False" Minimum="0.0" Maximum="1.0" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch"/> 

いくつかの問題。今度は最初にShiftを押してからドラッグしなければなりません。ドラッグしてからシフトすると、親指が後ろに飛びます。

私はどこかのロジックが不足しています。

アドバイスはありますか?

はあなた、あなたが何ができるか

答えて

2

ありがとう、あなたはドラッグの現在の「速さ」を扱うことができるようにValueへの変更ごとに1回の反復を処理しています。

この例では、私はあなたが(などSliderProgressBarRangeBaseに基づいて任意のコントロールのようなDependencyProperties MinimumMaximumValueを持っていると仮定しています。

この例では、変数の多くは不必要なであり、唯一の計算の手順を発揮するのに役立つ

private void CMiXSlider_OnDragStarted(object sender, DragStartedEventArgs e) 
{ 
    _lastPos = GetMousePosition(); 
} 

private double GetMousePosition() 
{ 
    return Mouse.GetPosition(this).X; 
} 

private void CMiXSlider_OnDragDelta(object sender, DragDeltaEventArgs e) 
{ 
    double thumbPosition = GetMousePosition(); 
    double deltaX = thumbPosition - _lastPos; 
    _lastPos = thumbPosition; 

    if (Keyboard.IsKeyDown(Key.LeftShift)) 
     deltaX /= 2; 

    double effectiveLength = ActualWidth - CMiXSlider.ActualWidth; 
    double effectiveChange = deltaX/effectiveLength; 
    double valueRange = Maximum - Minimum; 

    Value = Math.Min(Maximum, Math.Max(Minimum, Value + effectiveChange * valueRange)); 

    RepositionThumb(); 
} 

private void RepositionThumb() 
{ 
    double relativePosition = (Value - Minimum)/(Maximum - Minimum); 
    double absolutePosition = (ActualWidth - CMiXSlider.ActualWidth) * relativePosition; 
    CMiXSlider.Margin = new Thickness(absolutePosition,0,0,0); 
} 

は次のようになります。また

Thumb Animation

(場合をこれは「正確」ではありません)、最後の位置に基づいて変更を処理することができますの状態 w変更されました。

参照のための完全なコード:

のC#:

using System; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Controls.Primitives; 
using System.Windows.Input; 

namespace ShiftSlider 
{ 
    public partial class CustomSlider : UserControl 
    { 
     public static readonly DependencyProperty MinimumProperty = DependencyProperty.Register(
      "Minimum", typeof(double), typeof(CustomSlider), new PropertyMetadata((double)0.0)); 

     public double Minimum 
     { 
      get { return (double) GetValue(MinimumProperty); } 
      set { SetValue(MinimumProperty, value); } 
     } 

     public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register(
      "Maximum", typeof(double), typeof(CustomSlider), new PropertyMetadata((double)100.0)); 

     public double Maximum 
     { 
      get { return (double) GetValue(MaximumProperty); } 
      set { SetValue(MaximumProperty, value); } 
     } 

     public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
      "Value", typeof(double), typeof(CustomSlider), new PropertyMetadata(default(double))); 

     private double _lastPos; 

     public double Value 
     { 
      get { return (double) GetValue(ValueProperty); } 
      set { SetValue(ValueProperty, value); } 
     } 

     public CustomSlider() 
     { 
      InitializeComponent(); 
     } 

     private void CMiXSlider_OnDragStarted(object sender, DragStartedEventArgs e) 
     { 
      e.Handled = true; 
      _lastPos = GetMousePosition(); 
     } 

     private double GetMousePosition() 
     { 
      return Mouse.GetPosition(this).X; 
     } 

     private void CMiXSlider_OnDragDelta(object sender, DragDeltaEventArgs e) 
     { 
      e.Handled = true; 
      double thumbPosition = GetMousePosition(); 
      double deltaX = thumbPosition - _lastPos; 
      _lastPos = thumbPosition; 

      if (Keyboard.IsKeyDown(Key.LeftShift)) 
       deltaX /= 2; 

      double effectiveLength = ActualWidth - CMiXSlider.ActualWidth; 
      double effectiveChange = deltaX/effectiveLength; 
      double valueRange = Maximum - Minimum; 

      Value = Math.Min(Maximum, Math.Max(Minimum, Value + effectiveChange * valueRange)); 

      RepositionThumb(); 
     } 

     private void RepositionThumb() 
     { 
      double relativePosition = (Value - Minimum)/(Maximum - Minimum); 
      double absolutePosition = (ActualWidth - CMiXSlider.ActualWidth) * relativePosition; 
      CMiXSlider.Margin = new Thickness(absolutePosition,0,0,0); 
     } 

     private void CMiXSlider_OnDragCompleted(object sender, DragCompletedEventArgs e) 
     { 
      // 
     } 
    } 
} 

XAML:

<UserControl x:Class="ShiftSlider.CustomSlider" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" d:DesignWidth="300" d:DesignHeight="20"> 
    <Grid> 
     <Rectangle Fill="LightGray" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/> 
     <Thumb VerticalAlignment="Stretch" HorizontalAlignment="Left" Width="20" Name="CMiXSlider" 
       DragStarted="CMiXSlider_OnDragStarted" DragDelta="CMiXSlider_OnDragDelta" 
       DragCompleted="CMiXSlider_OnDragCompleted"/> 
    </Grid> 
</UserControl> 

あなただけでは `ActualWidth`を見つける、ハイテク

private void thumb_MouseEnter(object sender, MouseEventArgs e) 
{ 
    /*if (e.LeftButton == MouseButtonState.Pressed && e.MouseDevice.Captured == null) 
    { 
     MouseButtonEventArgs args = new MouseButtonEventArgs(e.MouseDevice, e.Timestamp, MouseButton.Left); 
     args.RoutedEvent = MouseLeftButtonDownEvent; 
     (sender as Thumb).RaiseEvent(args); 
    }*/ 
} 

Point pStart; 
bool isDragging; 
private bool shiftDown; 
private double startValue; 

private void CMiXSlider_DragStarted(object sender, DragStartedEventArgs e) 
{ 
    isDragging = true; 
    pStart = Mouse.GetPosition(CMiXSlider); 
    shiftDown = Keyboard.IsKeyDown(Key.LeftShift); 
    startValue = Value; 
} 

private void CMiXSlider_DragDelta(object sender, DragDeltaEventArgs e) 
{ 
    bool newShiftDown = Keyboard.IsKeyDown(Key.LeftShift); 

    double scale = newShiftDown ? 0.5 : 1; 

    Point pCurrent = Mouse.GetPosition(CMiXSlider); 

    if (newShiftDown != shiftDown) 
    { 
     shiftDown = newShiftDown; 
     pStart = pCurrent; 
     startValue = Value; 
    } 

    Point pDelta = new Point(pCurrent.X - pStart.X, pCurrent.Y - pStart.Y); 

    Value = startValue + (pDelta.X/CMiXSlider.ActualWidth) * scale; 

    if (Value >= 1.0) 
    { 
     Value = 1.0; 
    } 
    else if (Value <= 0.0) 
    { 
     Value = 0.0; 
    } 
} 

private void CMiXSlider_DragCompleted(object sender, DragCompletedEventArgs e) 
{ 
    isDragging = false; 
} 

private void CMiXSlider_KeyDown(object sender, KeyEventArgs e) 
{ 

    /*if (Keyboard.IsKeyDown(Key.LeftShift) && isDragging == true) 
    { 
     pStart = Mouse.GetPosition(CMiXSlider); 
    }*/ 
} 
+0

をコントロールするための更新'CMiXSlider.ActualWidth'と同じですので、effectiveChang eは無限大またはNaNです。 – lecloneur

+0

@lecloneur 'Thumb'として' CMiXSlider'を使用しましたので、あなたの場合はおそらく代わりに 'thumb0.ActualWidth'を使う必要があります。それ以上の問題がある場合は、完全なコード(XAMLを含む)を投稿してください。 –

+0

がXAMLを追加しました – lecloneur

関連する問題