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

MAUI自定义ContentView中MediaElement的事件如何在外部页面订阅

MAUI自定义ContentView中MediaElement的事件如何在外部页面订阅

我明白你现在的困扰——你封装了一个带MediaElement的自定义ContentView,绑定属性都正常工作,但想在使用这个控件的页面里监听MediaElement的事件(比如StateChanged、MediaOpened),直接访问内部的mediaElement会报CS1061错误,试了用Action属性又没触发效果。别着急,咱们可以通过在自定义控件中暴露对应的事件,把内部MediaElement的事件转发给外部页面,完美解决这个问题。

解决方案步骤

1. 在自定义控件MediaControl中暴露对应事件

打开MediaControl.xaml.cs,在类里声明和内部MediaElement匹配的事件,这样外部页面就能订阅这些事件了:

namespace NerdNewsNavigator2.Controls;

public partial class MediaControl : ContentView
{
    // 新增:暴露供外部订阅的事件,和MediaElement的事件一致
    public event EventHandler<MediaStateChangedEventArgs>? StateChanged;
    public event EventHandler? MediaOpened;

    // 你的现有属性、构造函数等代码...
}

2. 绑定内部MediaElement事件到自定义事件

在MediaControl的构造函数里,把内部mediaElement的事件触发逻辑绑定到我们刚声明的自定义事件上,这样内部事件触发时,外部订阅的事件也会跟着触发:

public MediaControl()
{
    InitializeComponent();
    PlayPosition = string.Empty;
    mediaElement.PropertyChanged += MediaElement_PropertyChanged;
    mediaElement.PositionChanged += ChangedPosition;
    CurrentPage = Shell.Current.CurrentPage;

    // 新增:转发内部MediaElement的事件到自定义事件
    mediaElement.StateChanged += (sender, e) => StateChanged?.Invoke(sender, e);
    mediaElement.MediaOpened += (sender, e) => MediaOpened?.Invoke(sender, e);
}

3. 在外部页面(比如TabletPlayPodcastPage)订阅事件

首先在页面的XAML里确保你给MediaControl设置了命名(比如x:Name="myMediaControl"):

<controls:MediaControl x:Name="myMediaControl" />

然后修改你的Load方法,直接订阅myMediaControl暴露的事件即可,不会再出现CS1061错误:

public void Load()
{
#if WINDOWS || ANDROID
    myMediaControl.MediaOpened += Seek;
#endif
#if IOS || MACCATALYST
    myMediaControl.StateChanged += SeekIOS;
#endif
}

为什么之前的Action属性没用?

你之前尝试添加的Action<object, EventArgs> MediaOpened只是一个委托属性,但你没有在内部mediaElement.MediaOpened触发时主动调用这个委托,所以外部订阅了也不会收到任何通知。而用.NET标准的事件模型,我们通过转发逻辑确保内部事件触发时,外部的订阅者能及时收到回调。

额外提醒:避免内存泄漏

记得在页面卸载时取消订阅事件,防止内存泄漏:

protected override void OnDisappearing()
{
    base.OnDisappearing();
    // 取消订阅事件
    myMediaControl.StateChanged -= SeekIOS;
    myMediaControl.MediaOpened -= Seek;
}

这样修改后,你就能在外部页面正常监听自定义控件中MediaElement的事件了,既保持了代码的封装性,又实现了你想要的事件回调功能。

备注:内容来源于stack exchange,提问作者James Crutchley

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 10:52:37