How do I bind a video to MediaElement's Source?

99 views Asked by At

I'm working off of James Montemagno's Monkey Finder app.

https://github.com/jamesmontemagno/MonkeysApp-Workshop

I'm trying to add a video to the details page, but I'm getting an error at runtime when I try to bind a new property called "Video" to the MediaElement Source. It works if I hardcode the file but not when I try to bind it, so MediaElement is set up correctly. It's just the binding that doesn't work.

The debugger breaks here:

#if DEBUG && !DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION
            UnhandledException += (sender, e) =>
            {
                if (global::System.Diagnostics.Debugger.IsAttached) global::System.Diagnostics.Debugger.Break();
            };
#endif

I added the attribute to the class:

public class Monkey
{
     ...     
     public string Video { get; set; }
}

I added the attribute and it's value to the json file for every entry:

{
     ...
     "Video": "testvid1.mp4"
},

I added the MediaElement to DetailsPage.xaml:

<toolkit:MediaElement x:Name="current_video"
WidthRequest="300" HeightRequest="200"
Source="{Binding Monkey.Video}"
ShouldShowPlaybackControls="True"
ShouldAutoPlay="True"/>

It does not like the Source line. I found some related discussions about it online and it appears it may be a bug, but I can't make sense of the discussion or proposed workarounds as I'm fairly new to .NET.

Am I missing something obvious?

---------------EDIT---------------

I fixed the path to the video file, so I no longer trigger a break. However, the video appears blank.

This works:

<toolkit:MediaElement x:Name="current_video"
WidthRequest="700" HeightRequest="500"                                  
Source="embed://testvid1.mp4"
ShouldShowPlaybackControls="True"
ShouldAutoPlay="True"/>

This does not work:

<toolkit:MediaElement x:Name="current_video"
WidthRequest="700" HeightRequest="500"                                  
Source="{Binding Monkey.Video}"
ShouldShowPlaybackControls="True"
ShouldAutoPlay="True"/>

The Monkey class has a Video property of type string:

public class Monkey
{
...
    public string Video { get; set; }
}

The json file has a value assigned to that property:

{
...
    "Video": "embed://testvid1.mp4"
},

The video is located in Resources/Raw.

If it helps or changes the solution to this problem, I would prefer to store the videos on the Android device instead of inside the app. This is only going to run on Android and will only be used by me.

Contents of .csproj file:

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks>
        <TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows')) and '$(MSBuildRuntimeType)' == 'Full'">$(TargetFrameworks);net8.0-windows10.0.19041</TargetFrameworks>
        <OutputType>Exe</OutputType>
        <RootNamespace>MonkeyFinder</RootNamespace>
        <UseMaui>true</UseMaui>
        <SingleProject>true</SingleProject>
        <ImplicitUsings>enable</ImplicitUsings>

        <!-- Display name -->
        <ApplicationTitle>MonkeyFinder</ApplicationTitle>

        <!-- App Identifier -->
        <ApplicationId>com.companyname.monkeyfinder</ApplicationId>
        <ApplicationIdGuid>ECD44DAE-B03E-4D8B-B427-71865961E696</ApplicationIdGuid>

        <!-- Versions -->
        <ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
        <ApplicationVersion>1</ApplicationVersion>
    </PropertyGroup>

    <ItemGroup>
        <!-- App Icon -->
        <MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" />

        <!-- Splash Screen -->
        <MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" />

        <!-- Images -->
        <MauiImage Include="Resources\Images\*" />
        <MauiImage Update="Resources\Images\dotnet_bot.svg" BaseSize="168,208" />

        <!-- Custom Fonts -->
        <MauiFont Include="Resources\Fonts\*" />

        <!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
        <MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
    </ItemGroup>

    <ItemGroup>
        <PackageReference Include="CommunityToolkit.Maui.MediaElement" Version="3.0.1" />
        <PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
        <PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
        <PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="$(MauiVersion)" />
    </ItemGroup>
</Project>
1

There are 1 answers

2
Jessie Zhang -MSFT On

From document Play local media, we could know that:

Note

The shorthand embed:// and filesystem:// only work from XAML. In code, please use MediaSource.FromResource() and MediaSource.FromFile() respectively. Using these methods, you can omit the embed:// and filesystem:// prefixes. The rest of the path should be the same.

So, if you want to use databinding to achieve this, you can try to define a variable of type MediaSource and load the video using code MediaSource.FromResource.

    public MediaSource Source { get; set; }

Then we can load the video from folder Resources/raw/testvid1.mp4 by using the following code:

    Source = MediaSource.FromResource("testvid1.mp4");

Usage example:

   <toolkit:MediaElement  
    HorizontalOptions="CenterAndExpand" HeightRequest="300"   
    x:Name="myMediaElement" 
    Source="{Binding Source}"
    ShouldShowPlaybackControls="True" />