Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding a progressbar to a mediaelement in wpf

In c#/wpf I added a progressbar and mediaelement to my window. The idea was that progressbar is displaying how much is been played in the mediaelement.

I tried it with the following 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>

I tried to bind the Maximum and Value property to the mediaelement. But when I load a mp3 for example into the mediaelement, nothing happends with the progressbar. (The music is playing so the mp3 is loaded and playing correctly).

I prefer to do this with a binding.

What am I doing here wrong?

like image 651
Peter Fortuin Avatar asked Oct 30 '10 10:10

Peter Fortuin


3 Answers

That is because Media is not opened and hence the progress bar is not aware of the maximum value. Try this...

Use the following events for MediaOpened, and MouseLeftButtonUp for your progress bar or slider. I tried it, and it works just fine.

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

The associate XAMl is as follows...

<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>
like image 113
Rahul Soni Avatar answered Oct 17 '22 07:10

Rahul Soni


I tried to bind the values and came to this, but without success:

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

Too bad it doesn't work.
I am afraid that you will need a timer set up.
Something like:

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

Kind regards,
Thimo.

like image 3
Thimo Braker Avatar answered Oct 17 '22 07:10

Thimo Braker


A WPF version of Rahul's sample with added real-time change of media position while sliding the bar.

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);
        }
    }
}
like image 1
glut Avatar answered Oct 17 '22 07:10

glut