How can I stop my slider from snapping back with isMoveToPointEnabled = true. (WPF C#)

Viewed 36

I am doing a small project for fun where I'm making a local music application (kinda like Spotify), and I would like for the slider I use for the music track (MusicSlider) to snap to where I click my mouse. I know you can do this with isMoveToPointEnabled = true, but since I have a really messy timer_tick (Update) function and whatnot, I haven't found a way of making it work properly.

I have tried for so long, and nothing my small brain comes up with works.

The problem is: Whenever I click on the slider like I should do, It immediately just snaps back.

The code is really messy because of the fact i'm not good at making clean code, and that the code has undergone a lot of brainstorming, and I haven't taken the time to fix it up yet.

Anyways, here is the code:

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Music_Application.MVVM.View;
using System.Globalization;
using Music_Application.MVVM.ViewModel;
using Microsoft.Win32;
using System.Windows.Controls.Primitives;
using System.Windows.Media.Animation;
using System.Threading;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;

namespace Music_Application
{
    public partial class MainWindow : Window
    {
        bool songProgressDrag;

        public bool fadeIn;
        public bool fadeOut;

        public double i;

        StreamWriter? sw;
        StreamReader? sr;

        System.Windows.Threading.DispatcherTimer timer = new System.Windows.Threading.DispatcherTimer();

        public MainWindow()
        {
            InitializeComponent();

            VolumeSlider.Value = Read(VolumeSlider.Value, "./Data/VolumeSave.txt");

            MusicPlayer.mediaPlayer.Open(new Uri("./Example Items/Music/NeverGonnaGiveYouUp.mp3", UriKind.RelativeOrAbsolute));

            MusicSlider.AddHandler(MouseLeftButtonDownEvent, new MouseButtonEventHandler(WhenMovingMusicSlider), true);
            MusicSlider.AddHandler(MouseLeftButtonUpEvent, new MouseButtonEventHandler(SyncMusicProgressToSlider), true);

            
            timer.Interval = TimeSpan.FromSeconds(0.01);
            timer.Tick += Update;
            timer.Start();

        }

        private void SongProgress_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double>? e)
        {
            UpdateSongProgress();
        }

        private void ChooseSong(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "MP3 files (*.mp3)|*.mp3|All files (*.*)|*.*";
            openFileDialog.Multiselect = false;
            if (openFileDialog.ShowDialog() == true)
            {
                MusicPlayer.mediaPlayer.Open(new Uri(openFileDialog.FileName));
                TagLib.File tagFile = TagLib.File.Create(openFileDialog.FileName);

                TagLib.IPicture coverArt = tagFile.Tag.Pictures[0];

                if(coverArt != null)
                {
                    MemoryStream ms = new MemoryStream(coverArt.Data.Data);
                    ms.Seek(0, SeekOrigin.Begin);

                    BitmapImage bitmap = new BitmapImage();
                    bitmap.BeginInit();
                    bitmap.StreamSource = ms;
                    bitmap.EndInit();

                    SongCover.ImageSource = bitmap;
                }

                SongName.Text = tagFile.Tag.Title;
                ArtistName.Text = tagFile.Tag.FirstAlbumArtist;

                MusicPlayer.mediaPlayer.Open(new Uri(openFileDialog.FileName, UriKind.RelativeOrAbsolute));

                if (MusicPlayer.isPlaying)
                {
                    MusicPlayer.mediaPlayer.Play();
                }

                MusicSlider.Value = 0;

                while(!MusicPlayer.mediaPlayer.NaturalDuration.HasTimeSpan)
                {
                    
                }

                
            }
        }

        bool nisse;

        private void SyncMusicProgressToSlider(object sender, MouseButtonEventArgs e)
        {
            while(MusicPlayer.mediaPlayer.Position != TimeSpan.FromSeconds(MusicSlider.Value))
            {
                MusicPlayer.mediaPlayer.Position = TimeSpan.FromSeconds(MusicSlider.Value);
            }

            songProgressDrag = false;
        }

        private void WhenMovingMusicSlider(object sender, MouseButtonEventArgs e)
        {
            songProgressDrag = true;
        }

        void Update(object? sender, EventArgs e)
        {
            if (MusicPlayer.mediaPlayer.NaturalDuration.HasTimeSpan)
            {

                if (!songProgressDrag && MusicPlayer.isPlaying)
                {
                    MusicSlider.Value = MathF.Round((float)MusicPlayer.mediaPlayer.Position.TotalSeconds);
                }
                if (MusicPlayer.repeat && MusicSlider.Value == MusicSlider.Maximum && !songProgressDrag)
                {
                    MusicPlayer.mediaPlayer.Position -= MusicPlayer.mediaPlayer.Position;
                    MusicSlider.Value = 0;
                }
                if (!MusicPlayer.repeat && MusicSlider.Value == MusicSlider.Maximum && !songProgressDrag)
                {
                    MusicPlayer.mediaPlayer.Position -= MusicPlayer.mediaPlayer.Position;
                    MusicSlider.Value = 0;
                    PlayButton.IsChecked = false;
                }
            }

            PlayButton.IsChecked = MusicPlayer.isPlaying;

            if (MusicPlayer.isPlaying)
            {
                PauseIcon.Visibility = Visibility.Visible;
                PlayIcon.Visibility = Visibility.Hidden;
            }
            else
            {
                PauseIcon.Visibility = Visibility.Hidden;
                PlayIcon.Visibility = Visibility.Visible;
            }

            if (fadeIn)
            {
                if (MusicPlayer.mediaPlayer.Volume < VolumeSlider.Value / 100)
                {
                    i += VolumeSlider.Value / 100 / 12;
                    MusicPlayer.mediaPlayer.Volume = i;
                }
                else
                {
                    MusicPlayer.mediaPlayer.Volume = VolumeSlider.Value / 100;

                    fadeIn = false;
                }
            }

            if (fadeOut)
            {
                if (MusicPlayer.mediaPlayer.Volume > 0)
                {
                    i -= VolumeSlider.Value / 100 / 12;
                    MusicPlayer.mediaPlayer.Volume = i;
                }
                else
                {
                    MusicPlayer.mediaPlayer.Volume = 0;

                    MusicPlayer.Pause();

                    MusicSlider.Value = MathF.Round((float)MusicPlayer.mediaPlayer.Position.TotalSeconds);

                    fadeOut = false;
                }
            }

            UpdateSongProgress();
        }

        private void UpdateSongProgress()
        {
            MusicSlider.Maximum = Convert.ToDouble(MathF.Round((float)MusicPlayer.mediaPlayer.NaturalDuration.TimeSpan.TotalSeconds));

            TimeSpan length = TimeSpan.FromSeconds(MathF.Round((float)Convert.ToDouble(MusicPlayer.mediaPlayer.NaturalDuration.TimeSpan.TotalSeconds)));
            TimeSpan progress = TimeSpan.FromSeconds(MusicSlider.Value);

            string songLength = string.Format("{0:D2}:{1:D2}",
                    length.Minutes,
                    length.Seconds);
            string songProgress = string.Format("{0:D2}:{1:D2}",
                progress.Minutes,
                progress.Seconds);

            if (songLength.Length == 5 && songLength.StartsWith("0"))
            {
                SongValueTotal.Text = songLength.Remove(0, 1);

            }
            else if (songLength.Length == 5 && !songLength.StartsWith("0"))
            {
                SongValueTotal.Text = songLength;
            }
            else if (songLength.Length == 8 && songLength.StartsWith("0"))
            {
                SongValueTotal.Text = songLength.Remove(0, 1);
            }
            else if (songLength.Length == 8 && !songLength.StartsWith("0"))
            {
                SongValueTotal.Text = songLength;
            }

            if (songProgress.Length == 5 && songProgress.StartsWith("0"))
            {
                SongValueProgress.Text = songProgress.Remove(0, 1);
            }

            else if (songProgress.Length == 5 && !songProgress.StartsWith("0"))
            {
                SongValueProgress.Text = songProgress;
            }
            else if (songProgress.Length == 8 && songProgress.StartsWith("0"))
            {
                SongValueTotal.Text = songLength.Remove(0, 1);
            }
            else if (songProgress.Length == 8 && !songProgress.StartsWith("0"))
            {
                SongValueTotal.Text = songLength;
            }
        }

        private void VolumeChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            MusicPlayer.mediaPlayer.Volume = VolumeSlider.Value / 100;
        }

        public void Pause(object sender, RoutedEventArgs e)
        {
            PauseIcon.Visibility = Visibility.Hidden;
            PlayIcon.Visibility = Visibility.Visible;

            MusicPlayer.isPlaying = false;

            fadeOut = true;
            fadeIn = false;
            i = VolumeSlider.Value / 100;
        }

        public void Play(object sender, RoutedEventArgs e)
        {
            PauseIcon.Visibility = Visibility.Visible;
            PlayIcon.Visibility = Visibility.Hidden;
            if (MusicPlayer.mediaPlayer.NaturalDuration.HasTimeSpan)
            {
                MusicPlayer.Play();
            }

            MusicPlayer.isPlaying = true;

            fadeIn = true;
            fadeOut = false;
            i = 0;
        }


        public void RepeatOn(object sender, RoutedEventArgs e)
        {
            RepeatButtonDot.Visibility = Visibility.Visible;

            MusicPlayer.repeat = true;
        }

        public void RepeatOff(object sender, RoutedEventArgs e)
        {
            RepeatButtonDot.Visibility = Visibility.Hidden;

            MusicPlayer.repeat = false;
        }

        protected override void OnClosed(EventArgs e)
        {
            Write(VolumeSlider.Value, "./Data/VolumeSave.txt");

            base.OnClosed(e);

            Application.Current.Shutdown();
        }

        private void Write(object sender, string url)
        {
            sw = new StreamWriter(url);

            sw.WriteLine(sender.ToString());

            sw.Close();
        }

        private double Read(object sender, string url)
        {
            sr = new StreamReader(url);

            sender = Convert.ToDouble(sr.ReadLine());

            sr.Close();

            return (double)sender;
        }

        private void FillHomeButton(object sender, RoutedEventArgs e)
        {
            HomeButtonSelected.Visibility = Visibility.Visible;
            HomeButtonUnselected.Visibility = Visibility.Hidden;

            HomeButtonText.Foreground = System.Windows.Media.Brushes.White;
        }

        private void UnfillHomeButton(object sender, RoutedEventArgs e)
        {
            HomeButtonUnselected.Visibility = Visibility.Visible;
            HomeButtonSelected.Visibility = Visibility.Hidden;

            HomeButtonText.Foreground = new SolidColorBrush(System.Windows.Media.Color.FromRgb(70,70,70)); /*(Brush) new BrushConverter().ConvertFrom("#b3b3b3");*/
        }



        private void ExitPlaylistCustomizer(object sender, RoutedEventArgs e)
        {
            CustomizePlaylistPopup.Visibility = Visibility.Hidden;
        }
    }










    public static partial class MusicPlayer
    {
        public static bool isPlaying;

        public static bool repeat;

        public static MediaPlayer mediaPlayer = new MediaPlayer();

        public static void Play()
        {
            var mainWindow = (MainWindow)Application.Current.MainWindow;

            if (mediaPlayer.NaturalDuration.HasTimeSpan)
            {
                mediaPlayer.Play();
            }

            isPlaying = true;

        }

        public static void Pause()
        {
            mediaPlayer.Pause();
            isPlaying = false;
        }
    }
}

And also, here is my slider in xaml in case you need it:

<Slider IsManipulationEnabled="True" TickFrequency="1" x:Name="MusicSlider" ValueChanged="SongProgress_ValueChanged" IsSnapToTickEnabled="True" IsMoveToPointEnabled="True" Style="{StaticResource Horizontal_Slider}" 
                    VerticalAlignment="Center" Margin="50,0,50,0"/>
1 Answers

The movement of slider thumb by clicking slider track seems not fire MouseLeftButtonDownEvent. As a result, you timer logic could revert slider's value before MouseLeftButtonUpEvent is fired.

I have no idea on direct solution for this issue. Perhaps it would be better to sync slider value and media player by ValueChanged event.

Related