Привязка progressbar к элементу mediaelement в wpf
в c# / wpf я добавил progressbar и mediaelement в мое окно. Идея заключалась в том, что progressbar показывает, сколько было воспроизведено в mediaelement.
я попробовал это со следующим 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>
Я попытался связать свойство Maximum и Value с элементом mediaelement. Но когда я загружаю mp3, например, в mediaelement, ничего не происходит с progressbar. (Музыка играет, поэтому mp3 загружается и воспроизводится правильно).
I предпочитаю делать это с привязкой.
что я здесь делаю неправильно?
5 ответов
это потому, что носитель не открывается, и, следовательно, индикатор выполнения не знает максимального значения. Попробовать это...
используйте следующие события для 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);
}
}
ассоциированный 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>
Я попытался связать значения и пришел к этому, но безуспешно:
<ProgressBar
x:Name="testProgressBar" Minimum="0"
Maximum="{Binding NaturalDuration.TimeSpan.TotalSeconds, ElementName=mediaPlayer}"
Value="{Binding Position.TotalSeconds, ElementName=mediaPlayer, Mode=OneWay}" />
жаль, что это не работает.
Боюсь,вам понадобится таймер.
Что-то вроде:
*.в 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;
}
}
С уважением,
Thimo.
просто посмотрите на этот пример-вместо progressbar он использовал слайдер...
присоединение поведения предварительного просмотра к элементу управления ползунка WPF
http://jobijoy.blogspot.com/2009/07/attaching-preview-behavior-to-wpf.html
версия WPF образца Рахула с добавленным в реальном масштабе времени изменением положения средств массовой информации пока сползающ адвокатское сословие.
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);
}
}
}
существует библиотека оболочки под названием ГУ.В WPF.СМИ в GitHub, который обрабатывает все проблемы MediaElement
и приносит больше.
Он поддерживает привязку к Position
собственность через TwoWay
привязка из коробки. Нет необходимости возиться с таймерами.