2014-03-01 47 views
2

我寫在Windows Phone上的音頻應用程序8.我已經創建了一個的MediaElement和尋求杆(滑)後:的Windows 8手機滑蓋綁定工作,只有點擊

<MediaElement x:Name="player" CurrentStateChanged="GetTrackDuration" /> 
<Slider x:Name="playerSeekBar" Value="{Binding ElementName=player, Path=Position, 
Mode=TwoWay, Converter={StaticResource PositionConverter}}" SmallChange="1" LargeChange="1"/> 

這是我的轉換器代碼:

public class PositionConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     double position = 0; 
     TimeSpan timespan = TimeSpan.Parse(value.ToString()); 
     position = timespan.TotalSeconds; 

     return position; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
      return TimeSpan.FromSeconds((double)value); 
    } 
} 

這裏是CurrentStateChanged事件代碼:

private void GetTrackDuration(object sender, RoutedEventArgs e) 
{ 
    var player = (MediaElement)sender; 
    if (player.CurrentState == System.Windows.Media.MediaElementState.Playing) 
     playerSeekBar.Maximum = player.NaturalDuration.TimeSpan.TotalSeconds; 
} 

這一切似乎工作確定,但牛逼這裏是綁定到滑塊的一個問題 - 它不會更新,直到我點擊應用程序內的某個地方 - 我的意思是我可以點擊一個沒有與滑塊或媒體元素連接的按鈕或空的空間。我點擊滑塊後正在更新,一切正常。順便說一句,音樂正常播放 - 即使在滑塊沒有被更新時開始。我試圖在互聯網上看,但我不知道該問什麼,這就是爲什麼我要求你尋求幫助。如果有人知道我可以在哪裏搜索解決方案,我將非常感激!:)

感謝您提前給予您的幫助!

回答

1

它看起來像一個問題時滑塊得到焦點,我試圖找到解決方案重定向焦點,但迄今爲止 - 我還沒有找到它。相反,我有一個不同勢提案,幾句話對你的代碼:

  1. 獲取的軌道持續時間時,當PlayState改變媒體沒有打開:

    private void player_MediaOpened(object sender, RoutedEventArgs e) 
    { 
        playerSeekBar.Maximum = (sender as MediaElement).NaturalDuration.TimeSpan.TotalSeconds; 
    } 
    
  2. 你的滑塊可能會被每一個小變化更新MediaElement的位置。我認爲這不是必需的 - 它可以每秒更新一次。所以我的建議是 - 你的滑塊綁定到一個屬性,並通知的PropertyChanged每一秒(使用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. 
    } 
    

在這種情況下,你不再需要轉換器,你的XAML代碼如下所示:

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

上面的代碼可能仍然需要一些改進,但工作得很好。

編輯 - 法無數據綁定和INotifyPropertyChanged的

您也可以完成你的任務更簡單的方法沒有約束力,只是用TimerLostMouseCapture

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

在XAML:

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

希望這有助於。

+0

非常感謝您的回答!我嘗試使用你所說的話,但是出現了一個小問題 - 當我將CurrentStateChanged中的事件更改爲MediaOpen時,那麼我的滑塊移動速度太快,並且很快就會結束。目前我不知道爲什麼它會這樣。仍然感謝您的幫助!:) –

+0

@RomanPylypets這很奇怪,因爲我檢查它應該工作。請檢查調試模式傳遞給Slider.Maximum的值。 – Romasz

+0

@RomanPylypets我已經添加了另一種管理滑塊的方式 - 如果你不需要綁定。 – Romasz