Windows phone 8 slider binding works only after a click

北城以北 提交于 2019-12-06 14:21:37

It looks like a problem when Slider gets Focus, I've tried to find a solution with redirecting Focus, but so far - I haven't found it. Instead I've a diffrent proposal and few remarks to your code:

  1. Get track duration when Media is Opened not when PlayState changes:

    private void player_MediaOpened(object sender, RoutedEventArgs e)
    {
        playerSeekBar.Maximum = (sender as MediaElement).NaturalDuration.TimeSpan.TotalSeconds;
    }
    
  2. Your Slider will probably be updated every little change of MediaElement's position. I think it isn't needed - it can be updated for example every second. So my proposal is - bind your Slider to a property, and notify PropertyChanged every second (use DispatcherTimer):

    // In this case we need INotifyPropertyChanged - 
    public partial class MainPage : PhoneApplicationPage, INotifyPropertyChanged
    {
    
    // implementing interface
    public event PropertyChangedEventHandler PropertyChanged;
    public void RaiseProperty(string property = null)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(property));
    }
    
    // Property for Binding
    public double SlideValue
    {
        get { return player.Position.TotalSeconds; }
        set { player.Position = TimeSpan.FromSeconds(value); }
    }
    
    DispatcherTimer timer = new DispatcherTimer(); // timer
    
    // Get the duration when Media File is opened
    private void player_MediaOpened(object sender, RoutedEventArgs e)
    {
        playerSeekBar.Maximum = (sender as MediaElement).NaturalDuration.TimeSpan.TotalSeconds;
    }
    
    public MainPage()
    {
        InitializeComponent();
        this.DataContext = this;  // Set the DataContext
        Play.Click += Play_Click;  // My play method
        timer.Interval = TimeSpan.FromSeconds(1);
        timer.Tick += (s, e) => { RaiseProperty("SlideValue"); };
    }
    
    private void Play_Click(object sender, RoutedEventArgs e)
    {
        player.AutoPlay = true;
        player.Source = new Uri("music.mp3", UriKind.RelativeOrAbsolute);
        timer.Start();  // DON'T forget to start the timer.
    }
    

In this case you no longer need Converters, and your XAML code can look like this:

<MediaElement x:Name="player" MediaOpened="player_MediaOpened"/>
<Slider x:Name="playerSeekBar" Value="{Binding SlideValue, Mode=TwoWay}" SmallChange="1" LargeChange="1"/>

Above code probably still needs some improvements, but works quite fine.

EDIT - method without DataBinding and INotifyPropertyChanged

You can also accomplish your task simpler way without Binding, just using Timer and LostMouseCapture:

public partial class MainPage : PhoneApplicationPage
{
    private double totalSeconds = 1;

    DispatcherTimer timer = new DispatcherTimer();

    private void player_MediaOpened(object sender, RoutedEventArgs e)
    {
        totalSeconds = (sender as MediaElement).NaturalDuration.TimeSpan.TotalSeconds;
    }

    public MainPage()
    {
        InitializeComponent();
        Play.Click += Play_Click;
        timer.Interval = TimeSpan.FromSeconds(1);
        timer.Tick += (s, e) => { playerSeekBar.Value += (double)(1 / totalSeconds); };
        playerSeekBar.LostMouseCapture += (s, e) =>
        { player.Position = TimeSpan.FromSeconds(playerSeekBar.Value * totalSeconds); };
    }

    private void Play_Click(object sender, RoutedEventArgs e)
    {
        player.AutoPlay = true;
        player.Source = new Uri("music.mp3", UriKind.RelativeOrAbsolute);
        timer.Start();  // DON'T forget to start the timer.
    }
}

In XAML:

<MediaElement x:Name="player" MediaOpened="player_MediaOpened"/>
<Slider x:Name="playerSeekBar" Value="0" SmallChange="0.01" Maximum="1.0"/>

Hope this helps.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!