XAML 如何在isMoveToPointEnabled = true的情况下阻止滑块恢复对齐,(WPF C#)

lhcgjxsq  于 2022-12-07  发布在  C#
关注(0)|答案(1)|浏览(172)

我正在做一个有趣的小项目,我正在制作一个本地音乐应用程序(有点像Spotify),我希望音乐轨道的滑块(MusicSlider)能够捕捉到我点击鼠标的位置。我知道你可以使用isMoveToPointEnabled = true来实现这一点,但是由于我有一个非常混乱的timer_tick(Update)函数等等,我还没有找到一种方法来使它正常工作。
我试了这么久,我的小脑袋想出来的都不管用。
问题是:每当我点击滑块像我应该做的,它立即只是snaps回来。
代码真的很乱,因为我不擅长编写干净的代码,而且代码经历了很多头脑 Storm ,我还没有花时间去修复它。
下面是代码:

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;
        }
    }
}

另外,这里是我在xaml中的滑块,如果你需要的话:

<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"/>
ugmeyewa

ugmeyewa1#

通过单击滑块轨道移动滑块似乎不会触发MouseLeftButtonDownEvent。因此,计时器逻辑可能会在触发MouseLeftButtonUpEvent之前还原滑块的值。
我不知道这个问题的直接解决方案。也许通过ValueChanged事件同步滑块值和媒体播放器会更好。

相关问题