2010-10-30 9 views
8

W języku C#/wpf dodałem pasek postępu i element multimedialny do mojego okna. Pomysł polegał na tym, że pasek postępu pokazuje, ile zostało zagrane w media-elicie.Powiązanie paska postępu z elementem nośnika w wpf

próbowałem go z poniższej XAML:

<Window x:Class="TestApp.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="627" Width="889"> 
    <Grid> 
    <MediaElement Margin="152,8,140,41" Name="mediaElement1" MediaEnded="mediaElement1_MediaEnded" Visibility="Hidden" /> 
    <ProgressBar Height="23" Margin="152,8,10,0" Name="mp3PlayingProgressBar" VerticalAlignment="Top" Foreground="DarkBlue" Maximum="{Binding Path=NaturalDuration.TimeSpan.TotalSeconds, Mode=OneWay, ElementName=mediaElement1}" Value="{Binding Path=Position.TotalSeconds, Mode=OneWay, ElementName=mediaElement1}" /> 
    </Grid> 
</Window> 

próbowałem powiązać maksimum i wartość nieruchomości do MediaElement. Ale kiedy ładuję mp3 na przykład w mediaement, nic nie dzieje się z paskiem postępu. (Muzyka jest odtwarzana, więc mp3 jest ładowane i odtwarzane poprawnie).

Wolę to zrobić z wiązaniem.

Co ja tu robię źle?

Odpowiedz

10

Dzieje się tak, ponieważ media nie są otwarte, a zatem pasek postępu nie jest świadomy maksymalnej wartości. Wypróbuj to ...

Użyj następujących zdarzeń dla MediaOpened i MouseLeftButtonUp dla paska postępu lub suwaka. Próbowałem i działa dobrze.

public partial class AudioPage : Page 
{ 
    TimeSpan _position; 
    DispatcherTimer _timer = new DispatcherTimer(); 

    public AudioPage() 
    { 
     InitializeComponent(); 
     _timer.Interval = TimeSpan.FromMilliseconds(1000); 
     _timer.Tick += new EventHandler(ticktock); 
     _timer.Start(); 
    } 

    void ticktock(object sender, EventArgs e) 
    { 
     sliderSeek.Value = media.Position.TotalSeconds; 
    } 

    // Executes when the user navigates to this page. 
    protected override void OnNavigatedTo(NavigationEventArgs e) 
    { 
    } 

    private void Play_Click(object sender, RoutedEventArgs e) 
    { 
     media.Play(); 
    } 

    private void Pause_Click(object sender, RoutedEventArgs e) 
    { 
     media.Pause(); 
    } 

    private void Stop_Click(object sender, RoutedEventArgs e) 
    { 
     media.Stop(); 
    } 

    private void media_MediaOpened(object sender, RoutedEventArgs e) 
    { 
     _position = media.NaturalDuration.TimeSpan; 
     sliderSeek.Minimum = 0; 
     sliderSeek.Maximum = _position.TotalSeconds; 
    } 

    private void sliderSeek_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
    { 
     int pos = Convert.ToInt32(sliderSeek.Value); 
     media.Position = new TimeSpan(0, 0, 0, pos, 0); 
    } 
} 

Stowarzyszonej XAML jest następująca ...

<Grid x:Name="LayoutRoot" Background="#FFFFE8E8"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="220*" /> 
     <RowDefinition Height="75*" /> 
    </Grid.RowDefinitions> 
    <MediaElement Height="189" HorizontalAlignment="Left" Margin="12,12,0,0" Name="media" VerticalAlignment="Top" Width="399" Source="anyfile.mp3" AutoPlay="True" MediaOpened="media_MediaOpened" /> 
    <StackPanel Orientation="Horizontal" Grid.Row="1" Height="30" Margin="12,8,163,37"> 
     <TextBlock Text="Volume" VerticalAlignment="Center"></TextBlock> 
     <Slider Margin="2" Maximum="1" Minimum="0" Width="102" Value="{Binding Path=Volume, Mode=TwoWay, ElementName=media}"></Slider> 
     <TextBlock Text="{Binding ElementName=media, Path=Volume, Mode=OneWay, StringFormat=0.00}" VerticalAlignment="Center" /> 
    </StackPanel> 
    <StackPanel Orientation="Horizontal" Grid.Row="1" Height="30" Margin="26,47,163,-2"> 
     <TextBlock Text="Seek" VerticalAlignment="Center"></TextBlock> 
     <Slider Margin="2" Width="104" Name="sliderSeek" MouseLeftButtonUp="sliderSeek_MouseLeftButtonUp"></Slider> 
     <TextBlock Text="{Binding ElementName=sliderSeek, Path=Value, StringFormat=0}" VerticalAlignment="Center"></TextBlock> 
    </StackPanel> 
    <StackPanel Orientation="Horizontal" Grid.Row="1" Height="30" Margin="266,8,12,37"> 
     <Button Name="Play" Content="Play" Margin="2" Click="Play_Click" /> 
     <Button Name="Pause" Content="Pause" Margin="2" Click="Pause_Click" /> 
     <Button Name="Stop" Content="Stop" Margin="2" Click="Stop_Click" /> 
    </StackPanel> 
</Grid> 
+0

Aktualizujesz wartość za pomocą minutnika. Wolałem robić to z wiązaniem. Czy to nie możliwe? –

+1

Nie mogę powiedzieć, czy to możliwe, czy nie. Ale napisałem to rozwiązanie, ponieważ nie mogłem pracować z Binding.Zdałem sobie sprawę, że problem ma miejsce, ponieważ media się nie otwierają i zdecydowałem się napisać ten kod. Ktoś może mnie poprawić i zapewnić lepsze rozwiązanie. Zostanę nastawiony na ten wątek. –

4

próbowałem powiązać v doszedłem do tego, ale bez powodzenia:

<ProgressBar 
    x:Name="testProgressBar" Minimum="0" 
    Maximum="{Binding NaturalDuration.TimeSpan.TotalSeconds, ElementName=mediaPlayer}" 
    Value="{Binding Position.TotalSeconds, ElementName=mediaPlayer, Mode=OneWay}" /> 

Szkoda, że ​​to nie działa.
Obawiam się, że będziesz potrzebował ustawionego timera.
Coś jak:

* .xaml

<ProgressBar x:Name="testProgressBar" /> 

* .cs

public MainWindow() 
    { 
     InitializeComponent(); 
     DispatcherTimer timer = new DispatcherTimer(); 
     timer.Interval = TimeSpan.FromSeconds(1); 
     timer.Tick += timer_Tick; 
     timer.Start(); 
    } 
    private void timer_Tick(object sender, EventArgs e) 
    { 
     if (mediaPlayer.Source != null && mediaPlayer.NaturalDuration.HasTimeSpan) 
     { 
      testProgressBar.Minimum = 0; 
      testProgressBar.Maximum = mediaPlayer.NaturalDuration.TimeSpan.TotalSeconds; 
      testProgressBar.Value = mediaPlayer.Position.TotalSeconds; 
     } 
    } 

poważaniem
Thimo.

+2

Nie? Próbowałem tego, co osoba chciała wiedzieć, co nie działa, dlatego podałem alternatywę dla tego pytania. taki, który działa i ma taki skutek, jakiego jedno z pytań chce osiągnąć, a nie? Próbuję tylko pomóc temu, który prosi o pomoc, aw moich oczach jest to odpowiedź. Przeczytaj to dobrze. Po prostu nie można powiązać wartości czasu, który został przekazany w odtwarzaczu multimedialnym bezpośrednio do paska postępu, z powodu pewnych dziwnych decyzji podjętych przez Microsoft. –

+1

To jest odpowiedź, a właściwie dobra! Miałem dokładnie taki przypadek PO i ta odpowiedź rozwiązana działała dokładnie tak, jak tego chciałem dla mojego rozwiązania. :) – Milkncookiez

0

Wersja próbkowania Rahul z WPF z dodaną zmianą położenia mediów w czasie rzeczywistym podczas przesuwania paska.

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 

     _timer.Interval = TimeSpan.FromMilliseconds(1000); 
     _timer.Tick += new EventHandler(ticktock); 
     _timer.Start(); 

     Open(@"filename.mp3"); 
    } 
    public void Open(string fileName) 
    { 
     var uriPath = "file:///" + fileName.Replace("\\", "/"); 
     media.Source=new Uri(uriPath); 
    } 

    TimeSpan _position; 
    DispatcherTimer _timer = new DispatcherTimer(); 

    void ticktock(object sender, EventArgs e) 
    { 
     if (!sliderSeek.IsMouseCaptureWithin) 
      sliderSeek.Value = media.Position.TotalSeconds; 
    } 

    private void Play_Click(object sender, RoutedEventArgs e) 
    { 
     media.Play(); 
    } 

    private void Pause_Click(object sender, RoutedEventArgs e) 
    { 
     media.Pause(); 
    } 

    private void Stop_Click(object sender, RoutedEventArgs e) 
    { 
     media.Stop(); 
    } 

    private void media_MediaOpened(object sender, RoutedEventArgs e) 
    { 
     _position = media.NaturalDuration.TimeSpan; 
     sliderSeek.Minimum = 0; 
     sliderSeek.Maximum = _position.TotalSeconds; 
    } 

    private void sliderSeek_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
    {   
     int pos = Convert.ToInt32(sliderSeek.Value); 
     media.Position = new TimeSpan(0, 0, 0, pos, 0); 
    } 

    private void sliderSeek_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) 
    { 
     if (sliderSeek.IsMouseCaptureWithin) 
     { 
      int pos = Convert.ToInt32(sliderSeek.Value); 
      media.Position = new TimeSpan(0, 0, 0, pos, 0); 
     } 
    } 
} 
0

Jest biblioteka otoki nazywa Gu.Wpf.Media w GitHub, który obsługuje wszystkie problemy MediaElement i przynosi więcej.

Umożliwia powiązanie z wiązania po wyjęciu z pudełka. Nie musisz martwić się o zegary.

Powiązane problemy