You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# WPF中ItemTemplate内MediaElement实现无限循环播放的方法

解决方案

1. 实现无限循环播放

由于Storyboard方法无效,我们可以通过监听MediaElement的MediaEnded事件,在播放结束时重置播放位置并重新启动播放。为适配DataTemplate的场景,推荐用附加属性封装循环逻辑,避免后台代码直接操作UI元素:

创建附加属性类

public static class MediaElementHelper
{
    public static readonly DependencyProperty LoopEnabledProperty =
        DependencyProperty.RegisterAttached(
            "LoopEnabled", 
            typeof(bool), 
            typeof(MediaElementHelper), 
            new PropertyMetadata(false, OnLoopEnabledChanged));

    public static bool GetLoopEnabled(DependencyObject obj)
    {
        return (bool)obj.GetValue(LoopEnabledProperty);
    }

    public static void SetLoopEnabled(DependencyObject obj, bool value)
    {
        obj.SetValue(LoopEnabledProperty, value);
    }

    private static void OnLoopEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is MediaElement mediaElement)
        {
            if ((bool)e.NewValue)
            {
                mediaElement.MediaEnded += MediaElement_MediaEnded;
            }
            else
            {
                mediaElement.MediaEnded -= MediaElement_MediaEnded;
            }
        }
    }

    private static void MediaElement_MediaEnded(object sender, RoutedEventArgs e)
    {
        if (sender is MediaElement mediaElement)
        {
            mediaElement.Position = TimeSpan.Zero;
            mediaElement.Play();
        }
    }
}

在DataTemplate中启用循环

修改MosaicGridStyleMP4模板,给MediaElement添加附加属性:

<DataTemplate x:Key="MosaicGridStyleMP4">
<Border BorderBrush="Gray" BorderThickness="1" CornerRadius="10" Margin="2,2,2,2">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="60"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <TextBlock Text="{Binding PK_SpotABS}" Width="Auto" />
        <MediaElement x:Name="mePlayer" 
                      Source="{Binding Media.Source, Mode=OneWay}" 
                      Volume="0" 
                      Grid.Row="1"
                      local:MediaElementHelper.LoopEnabled="True"/>
    </Grid>
</Border>
</DataTemplate>

2. 添加播放/停止控制按钮

为每个列表项的ViewModel添加播放、停止命令,在DataTemplate中绑定命令并传递对应的MediaElement作为参数:

列表项ViewModel示例

假设列表项ViewModel为PageItemViewModel,添加控制命令:

public class PageItemViewModel : INotifyPropertyChanged
{
    public string PK_SpotABS { get; set; }
    public MediaInfo Media { get; set; }

    public ICommand PlayCommand { get; }
    public ICommand StopCommand { get; }

    public PageItemViewModel()
    {
        PlayCommand = new RelayCommand<MediaElement>(media =>
        {
            media.Position = TimeSpan.Zero;
            media.Play();
        });

        StopCommand = new RelayCommand<MediaElement>(media =>
        {
            media.Stop();
        });
    }

    // INotifyPropertyChanged接口实现代码...
}

注:RelayCommand是常见的ICommand实现,可自行定义或使用MVVM框架提供的实现

修改DataTemplate添加控制按钮

在模板中新增播放/停止按钮,绑定ViewModel的命令并传入当前MediaElement:

<DataTemplate x:Key="MosaicGridStyleMP4">
<Border BorderBrush="Gray" BorderThickness="1" CornerRadius="10" Margin="2,2,2,2">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="60"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="40"/>
        </Grid.RowDefinitions>
        <TextBlock Text="{Binding PK_SpotABS}" Width="Auto" />
        <MediaElement x:Name="mePlayer" 
                      Source="{Binding Media.Source, Mode=OneWay}" 
                      Volume="0" 
                      Grid.Row="1"
                      local:MediaElementHelper.LoopEnabled="True"/>
        <StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Center">
            <Button Content="播放" 
                    Margin="5"
                    Command="{Binding PlayCommand}"
                    CommandParameter="{Binding ElementName=mePlayer}"/>
            <Button Content="停止" 
                    Margin="5"
                    Command="{Binding StopCommand}"
                    CommandParameter="{Binding ElementName=mePlayer}"/>
        </StackPanel>
    </Grid>
</Border>
</DataTemplate>

简化方案(非MVVM场景)

如果不需要严格遵循MVVM,可直接在DataTemplate中给MediaElement绑定MediaEnded事件,后台代码实现循环:

<MediaElement x:Name="mePlayer" 
              Source="{Binding Media.Source, Mode=OneWay}" 
              Volume="0" 
              Grid.Row="1"
              MediaEnded="MePlayer_MediaEnded"/>

后台代码:

private void MePlayer_MediaEnded(object sender, RoutedEventArgs e)
{
    if (sender is MediaElement mediaElement)
    {
        mediaElement.Position = TimeSpan.Zero;
        mediaElement.Play();
    }
}

内容的提问来源于stack exchange,提问作者HegeGabi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 19:35:27