2010-10-30 12 views
8

In C#/wpf habe ich eine Fortschrittsleiste und ein Mediaelement zu meinem Fenster hinzugefügt. Die Idee war, dass die Fortschrittsleiste anzeigt, wie viel in dem Medienelement gespielt wurde.Binden einer Fortschrittsleiste an ein Mediaelement in WPF

Ich versuchte es mit dem folgenden 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> 

Ich versuchte, das Maximum und Value-Eigenschaft auf das Mediaelement zu binden. Aber wenn ich zum Beispiel ein mp3 in das Mediaelement lade, passiert nichts mit der Fortschrittsanzeige. (Die Musik spielt so, dass die MP3 geladen und korrekt abgespielt wird).

Ich bevorzuge dies mit einer Bindung zu tun.

Was mache ich hier falsch?

Antwort

10

Dies liegt daran, dass Media nicht geöffnet ist und daher der Fortschrittsbalken den Maximalwert nicht kennt. Versuchen Sie dies ...

Verwenden Sie die folgenden Ereignisse für MediaOpened und MouseLeftButtonUp für Ihre Fortschrittsleiste oder Schieberegler. Ich habe es versucht, und es funktioniert gut.

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

Der Associate XAML wird wie folgt ...

<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

Sie aktualisieren den Wert mit einem Timer. Ich habe es lieber mit einer Bindung gemacht. Ist das nicht möglich? –

+1

Ich kann nicht wirklich sagen, ob es möglich ist oder nicht. Aber ich habe diese Lösung geschrieben, da ich mit Binding nicht arbeiten konnte.Ich erkannte, dass das Problem passierte, weil die Medien nicht geöffnet wurden und ich beschloss, diesen Code zu schreiben. Jemand kann mich korrigieren und eine bessere Lösung anbieten. Ich werde auf diesen Thread abgestimmt bleiben. –

4

ich versuchte, die v zu binden und kam dazu, aber ohne Erfolg:

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

Schade, dass es nicht funktioniert.
Ich habe Angst, dass Sie einen Timer einrichten müssen.
Etwas wie:

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

Mit freundlichen Grüßen,
Thimo.

+2

Nicht? Ich habe versucht, was die Person wissen wollte, was nicht funktioniert, daher gab ich eine Alternative zu der Frage. eine, die funktioniert und hat die Wirkung, dass die eine Befragung erreichen will, nicht? Ich versuche nur denjenigen zu helfen, der um Hilfe bittet, und in meinen Augen ist es eine Antwort. Lesen Sie es gut. Es ist einfach nicht möglich, den Wert der Zeit, die im Media Player übergeben wurde, direkt an den Fortschrittsbalken zu binden, aufgrund einiger eigenartiger Entscheidungen, die Microsoft getroffen hat. –

+1

Es ist eine Antwort, und eigentlich eine gute! Ich hatte genau den Fall vom OP und diese Antwort löste genau das, was ich für meine Lösung wollte. :) – Milkncookiez

0

Eine WPF-Version von Rahuls Beispiel mit zusätzlicher Echtzeitänderung der Medienposition beim Verschieben der Leiste.

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

Es gibt eine Wrapper-Bibliothek Gu.Wpf.Media in GitHub genannt, die alle Probleme der MediaElement Griffe und bringt mehr.

Es unterstützt die Bindung an Position Eigenschaft über TwoWay Bindung aus der Box. Keine Notwendigkeit, mit Timern zu kämpfen.

Verwandte Themen