简体   繁体   English

剃刀组件中的C#StateHasChanged()不强制 <video> 标签以加载/更改mp4播放,仅使用javascript似乎有效

[英]C# StateHasChanged() in a razor component does not force <video> tag to load/change the mp4 playing, only using javascript seems to work

I am experimenting with server-side blazor. 我正在尝试使用服务器端的blazor。 I am trying to have multiple buttons set/change the .mp4 file playing in a tag in a razor component. 我试图在剃刀组件的标签中设置多个按钮来设置/更改播放的.mp4文件。 The only way I have found to make this work is calling a javascript function via IJSRuntime:InvokeVoidAsync() from the OnParametersSet() in my razor component. 我发现完成这项工作的唯一方法是从剃刀组件中的OnParametersSet()通过IJSRuntime:InvokeVoidAsync()调用javascript函数。 The javascript function is located in _Host.cshtml. javascript函数位于_Host.cshtml中。 This seems like a rather ugly solution to what should be a simple problem. 对于应该是一个简单问题的解决方案,这似乎是一个非常丑陋的解决方案。

I have tried using StateHasChanged() in the OnClick button functions. 我尝试在OnClick按钮函数中使用StateHasChanged()。 The h1-header tag and source src="NewFile" are shown to update when I look at the html render in chrome, and the h1 tag correctly changes on the page when a button is clicked, but the new video is not loaded. 当我查看chrome中的html渲染时,h1-header标签和源src =“ NewFile”显示为更新,并且当单击按钮但未加载新视频时,h1标签在页面上正确更改。 My guess is this is tied to the video playing on its own thread, or the video tag itself not changing. 我的猜测是,这与在其自己的线程上播放的视频有关,或者视频标签本身没有变化。 I just don't understand how to get this done it from razor/c#. 我只是不明白如何从razor / c#做到这一点。

Because of build errors, the Javascript code was added to File: _Html.cshtml 由于生成错误,因此将Javascript代码添加到了文件:_Html.cshtml

  <script>
        function loadVideo (strNewVideo)
        {
            document.getElementById('videoSourceId').src = strNewVideo;
            document.getElementById("videoTagId").load();
        }
    </script>

Simple component to play videos... File: VideoPlayer.razor 播放视频的简单组件... File:VideoPlayer.razor

@inject IJSRuntime theJavaScriptEngine;

<div class="align-content-center">
    <h1>@this.m_strRenderMe</h1>
    <video id="videoTagId" autoplay width="1080" height="720">
        <source id="videoSourceId" src=@this.m_strRenderMe type="video/mp4" />
    </video>
</div>

@code {
    ElementReference theVideoTag;

    [Parameter]
    public string strVideoFilePath { get; set; }

    private string m_strRenderMe;

    protected override void OnParametersSet()
    {
        this.m_strRenderMe = this.strVideoFilePath;

        theJavaScriptEngine.InvokeVoidAsync("loadVideo", this.m_strRenderMe);

        this.StateHasChanged();
    }
}

Razor Page with component from above and 4 buttons isw in File: Counter.razor 剃刀页面上方带有组件,文件中包含4个按钮:Counter.razor

@page "/counter"

@using UseBlazorToReadPowerPoint.Classes

@inject CPersistantAppState  thePersistantAppState


<VideoPlayer strVideoFilePath=@thePersistantAppState.m_strVideoPath></VideoPlayer>

<button class="btn btn-primary" @onclick="PlayVideo_1">Video 1</button>
<button class="btn btn-primary" @onclick="PlayVideo_2">Video 2</button>
<button class="btn btn-primary" @onclick="PlayVideo_3">Video 3</button>
<button class="btn btn-primary" @onclick="PlayVideo_4">Video 4</button>

@code {

    void PlayVideo_1()
        {
        thePersistantAppState.m_strVideoPath = "videos/Video-1.mp4";
        }

    void PlayVideo_2()
    {
        thePersistantAppState.m_strVideoPath = "videos/Video-2.mp4";
    }

    void PlayVideo_3()
    {
        thePersistantAppState.m_strVideoPath = "videos/Video-3.mp4";
    }

    void PlayVideo_4()
    {
        thePersistantAppState.m_strVideoPath = "videos/Video-4.mp4";
    }

}

To persist the filename selected. 保留所选文件名。 File: CPersistantAppState.cs 文件:CPersistantAppState.cs

namespace UseBlazorToReadPowerPoint.Classes
{
    public class CPersistantAppState
    {
        public string m_strVideoPath;
    }
}

The listed code works. 列出的代码有效。 I just cannot figure out how to make this work without the javascript call. 我只是不知道如何在没有JavaScript调用的情况下使这项工作有效。 Seems like there has to be a cleaner way of doing this. 似乎必须有一种更清洁的方式来执行此操作。

Issue is not with StateHasChangeg() , it is about html's Video tag : 问题不StateHasChangeg() ,而是关于html的Video标签

This method is generally only useful when you've made dynamic changes to the set of sources available for the media element, either by changing the element's src attribute or by adding or removing elements nested within the media element itself. 通常,仅当您通过更改元素的src属性或添加或删除嵌套在media元素自身中的元素对可用于media元素的源集进行了动态更改时,此方法才有用。 load() will reset the element and rescan the available sources, thereby causing the changes to take effect . load()将重置元素并重新扫描可用的源,从而使更改生效

It means that is mandatory invoke load after change src attribute. 这意味着更改src属性后必须执行调用load You can't invoke load from blazor at this time, it means you should to invoke it via IJSRuntime : 您目前无法从blazor调用load ,这意味着您应该通过IJSRuntime调用它:

Blazor code 开拓者代码

<div class="align-content-center">
    <h1>@m_strRenderMe[currentVideo]</h1>
    <button @onclick="ChangeVideo">Change video</button>
    <video id="videoTagId" autoplay width="1080" height="720">
        <source id="videoSourceId" src="@m_strRenderMe[currentVideo]" type="video/mp4" />
    </video>
</div>

@code
{
    int currentVideo = 0;
    string[] m_strRenderMe = new string[] {
        "https://.../videoplayback-1.mp4",
        "https://.../videoplayback-2.mp4"
    };
    protected void ChangeVideo()
    {
        currentVideo = (currentVideo + 1) % 2;
        theJavaScriptEngine.InvokeVoidAsync("loadVideo");
    }
}

JS code JS代码

<script>
    function loadVideo ()
    {
        document.getElementById("videoTagId").load();
    }
</script>

Check it out at BlazorFiddle . BlazorFiddle检查一下。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM