Window/WPF2010. 8. 13. 23:22

 

이번 포스팅은 Slider에 대한 내용입니다.

우리가 사용하고 있는 미디어 플레이어 같은 프로그램들은 아래와 같이 슬라이더 바의 어느 영역을

클릭하고 움직이더라도 해당 지점으로 슬라이더의 위치가 움직입니다.

 

 

하지만 Slider컨트롤을 사용해보면 Thumb 영역이 아닌 다음과 같은 빨간 영역을 클릭 하게 되면 해당 위치로

Thumb 이 움직이나 이 후에 마우스 왼쪽 버튼을 클릭한 상태에서 움직여 보아도 Thumb 은 따라 오질 않습니다.

 

 

이를 개선하기 위한 방법으로

SliderPreviewMouseMove 이벤트를 사용하여 Slider내의 마우스 좌표 값을 SliderValue 값으로 변경 하였습니다.

 

코드는 다음과 같습니다.

Slider를 상속받은 CustomSlider 클래스를 생성하였고 AutoMoveProperty 라는 프로퍼티를 만들어

프로퍼티 값 변경에 따라 작성한 PreviewMouseMove 이벤트를 연결 / 제거 합니다.

     class CustomSlider : Slider

    {

        // 이전 IsMoveToPointEnabled 값으로 되돌리기 위한 플래그

        private bool defaultIsMoveToPointEnabled;

 

        public static readonly DependencyProperty AutoMoveProperty =

            DependencyProperty.Register(

           "AutoMove",

           typeof(bool),

           typeof(CustomSlider),

           new FrameworkPropertyMetadata(false, ChangeAutoMoveProperty));

 

        public bool AutoMove

        {

            get { return (bool)GetValue(AutoMoveProperty); }

            set { SetValue(AutoMoveProperty, value); }

        }

 

        private static void ChangeAutoMoveProperty(DependencyObject d, DependencyPropertyChangedEventArgs e)

        {

            CustomSlider slider = d as CustomSlider;

 

            if (slider != null)

            {

                if ((bool)e.NewValue)

                {

                    slider.defaultIsMoveToPointEnabled = slider.IsMoveToPointEnabled;

                    slider.IsMoveToPointEnabled = true;

                    slider.PreviewMouseMove += CustomSlider_PreviewMouseMove;

                }

                else

                {

                    slider.IsMoveToPointEnabled = slider.defaultIsMoveToPointEnabled;

                    slider.PreviewMouseMove -= CustomSlider_PreviewMouseMove;

                }

            }

        }

 

        private static void CustomSlider_PreviewMouseMove(object sender, MouseEventArgs e)

        {

            if (e.LeftButton == MouseButtonState.Pressed)

            {

                CustomSlider slider = sender as CustomSlider;

 

                Point point = e.GetPosition(slider);

 

                // 현재 Slider 내 마우스 좌표 값을 Value 값으로 계산.

                slider.Value = point.X / (slider.ActualWidth / slider.Maximum);

            }

        }

    }

 

이를 Sliverlight에서 적용해보니 역시나 프로퍼티 오류등을 보이며 제대로 되지 않더군요. -_-

그래서 Sliverlight 환경에 맞게 다시 수정해 보았습니다.

 

크게 바뀐 점은 없고 Sliverlight 에서 없는 IsMoveToPointEnabled 프로퍼티를 삭제하고

WPF 와 달리 마우스 이벤트로 넘어온 인자를 통해 MouseButton의 상태를 알 수 없기 때문에 이를 확인하기 위해

마우스의 다운과 업 이벤트에서 플래그 값을 변경하였습니다.

또한 Slider의 마우스 다운과 업 이벤트를 발생시키 위해서 새로 핸들러를 추가하였습니다.

  public partial class CustomSlider : Slider

    {

        private bool IsMouseLeftDown;

 

        public static readonly DependencyProperty AutoMoveProperty =

            DependencyProperty.Register(

           "AutoMove",

           typeof(bool),

           typeof(CustomSlider),

           new PropertyMetadata(false, ChangeAutoMoveProperty));

 

        public bool AutoMove

        {

            get { return (bool)GetValue(AutoMoveProperty); }

            set { SetValue(AutoMoveProperty, value); }

        }

 

        public CustomSlider()

        {

            AddHandler(FrameworkElement.MouseLeftButtonDownEvent,

                new MouseButtonEventHandler(MouseLeftDown), true);

            AddHandler(FrameworkElement.MouseLeftButtonUpEvent,

                new MouseButtonEventHandler(MouseLeftUp), true);

        }

 

        private void MouseLeftDown(object sender, MouseButtonEventArgs e)

        {

            Point point = e.GetPosition(this);

            Value = point.X / (ActualWidth / Maximum);

            IsMouseLeftDown = true;

        }

 

        private void MouseLeftUp(object sender, MouseButtonEventArgs e)

        {

            IsMouseLeftDown = false;

        }

 

        private static void ChangeAutoMoveProperty(DependencyObject d, DependencyPropertyChangedEventArgs e)

        {

            CustomSlider slider = d as CustomSlider;

 

            if (slider != null)

            {

                if ((bool)e.NewValue)

                {

                    slider.MouseMove += CustomSlider_PreviewMouseMove;

                }

                else

                {

                    slider.MouseMove -= CustomSlider_PreviewMouseMove;

                }

            }

        }

 

        private static void CustomSlider_PreviewMouseMove(object sender, MouseEventArgs e)

        {

            CustomSlider slider = sender as CustomSlider;

           

            if (slider.IsMouseLeftDown)

            {

                Point point = e.GetPosition(slider);

 

                slider.Value = point.X / (slider.ActualWidth / slider.Maximum);

            }

        }

    }

 

- XAML 에서의 사용법은 다음과 같이 AutoMove 멤버의 값을 True로 설정함으로써 사용할 수 있습니다.

 

<local:CustomSlider VerticalAlignment="Center" AutoMove="True"/>


- 블랜드에서는 다음과 같이 AutoMove 를 체크하여 사용하 실 수 있습니다.

 

소스를 받아 테스트 해보시면 잘 따라 움직이는 것을 보실 수 있습니다.

'Window > WPF' 카테고리의 다른 글

ListBox ItemsPanel 변경하기  (0) 2011.03.04
Image Rotate  (4) 2010.11.04
[ WPF ] ClickOnce로 배포하기  (9) 2010.08.03
[ WPF ] RegisterWindowMessage 를 이용한 프로그램 간 메시지 보내기  (178) 2010.07.21
[ WPF ] BackgroundWorker  (2) 2010.07.11
Posted by 열ㅇl