将进度条绑定到wpf中的mediaelement

时间:2021-08-14 16:06:15

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.

在c#/ wpf中,我在窗口中添加了一个进度条和媒体元素。我们的想法是,进度条显示媒体元素的播放量。

I tried it with the following xaml:

我尝试使用以下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).

我试图将Maximum和Value属性绑定到mediaelement。但是当我将mp3加载到mediaelement时,进度条没有任何问题。 (正在播放音乐,因此mp3已加载并正常播放)。

I prefer to do this with a binding.

我更喜欢用绑定来做这件事。

What am I doing here wrong?

我在这做错了什么?

5 个解决方案

#1


10  

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

这是因为Media未打开,因此进度条不知道最大值。尝试这个...

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

对MediaOpened使用以下事件,对进度条或滑块使用MouseLeftButtonUp。我试过了,它运作得很好。

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

合作伙伴XAMl如下......

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

#2


4  

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

*的.xaml

<ProgressBar x:Name="testProgressBar" />

*.cs

*的.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.

亲切的问候,Thimo。

#3


0  

just have look at this example - instead of progressbar he used slider...

只是看看这个例子 - 而不是进度条,他使用了滑块......

Attaching Preview behavior to a WPF Slider control

将预览行为附加到WPF Slider控件

http://jobijoy.blogspot.com/2009/07/attaching-preview-behavior-to-wpf.html

http://jobijoy.blogspot.com/2009/07/attaching-preview-behavior-to-wpf.html

#4


0  

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

一个WPF版本的Rahul样本,在滑动条形图时增加了媒体位置的实时变化。

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

#5


0  

There is a wrapper library called Gu.Wpf.Media in GitHub that handles all the problems of the MediaElement and brings more.

在GitHub中有一个名为Gu.Wpf.Media的包装器库,它处理MediaElement的所有问题并带来更多。

It supports binding to Position property via TwoWay binding out of the box. No need to hassle with timers.

它支持通过TwoWay绑定开箱即用于绑定到Position属性。无需为计时器烦恼。

#1


10  

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

这是因为Media未打开,因此进度条不知道最大值。尝试这个...

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

对MediaOpened使用以下事件,对进度条或滑块使用MouseLeftButtonUp。我试过了,它运作得很好。

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

合作伙伴XAMl如下......

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

#2


4  

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

*的.xaml

<ProgressBar x:Name="testProgressBar" />

*.cs

*的.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.

亲切的问候,Thimo。

#3


0  

just have look at this example - instead of progressbar he used slider...

只是看看这个例子 - 而不是进度条,他使用了滑块......

Attaching Preview behavior to a WPF Slider control

将预览行为附加到WPF Slider控件

http://jobijoy.blogspot.com/2009/07/attaching-preview-behavior-to-wpf.html

http://jobijoy.blogspot.com/2009/07/attaching-preview-behavior-to-wpf.html

#4


0  

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

一个WPF版本的Rahul样本,在滑动条形图时增加了媒体位置的实时变化。

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

#5


0  

There is a wrapper library called Gu.Wpf.Media in GitHub that handles all the problems of the MediaElement and brings more.

在GitHub中有一个名为Gu.Wpf.Media的包装器库,它处理MediaElement的所有问题并带来更多。

It supports binding to Position property via TwoWay binding out of the box. No need to hassle with timers.

它支持通过TwoWay绑定开箱即用于绑定到Position属性。无需为计时器烦恼。