gpt4 book ai didi

c# - 在第二个窗口中显示视频(UWP C#)

转载 作者:行者123 更新时间:2023-11-30 23:01:40 25 4
gpt4 key购买 nike

我有一个正在使用的应用程序,我希望一个窗口成为控制器,另一个窗口成为视频播放器视图。

这样做的目的是控制在投影机上播放视频时可以从笔记本电脑上观看的一个窗口中播放视频。最终,我想对其进行设置,以便可以拥有一组16个视频,我可以使用键盘触发这些视频以在视频播放器视图中播放,当我按下与特定视频相关联的键(通过选择器选择)时,停止当前播放的视频)并开始播放新视频。

请注意,如果有更好的语言和/或系统来创建此Windows应用程序,除了我要询问的内容之外,我欢迎其他建议。

这是我的MainPage.xaml.cs:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel.Core;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Core;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace VideoSamplePlayer
{

public sealed partial class MainPage : Page
{
int newViewID = 0;

Window VideoPlayerWindow;

public MainPage()
{
this.InitializeComponent();

}

private async void Button_Click(object sender, RoutedEventArgs e)
{
if (newViewID == 0) {
var myView = CoreApplication.CreateNewView();

await myView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
Frame newFrame = new Frame();
newFrame.Navigate(typeof(VideoPlayer), null);

Window.Current.Content = newFrame;
Window.Current.Activate();
VideoPlayerWindow = Window.Current;

newViewID = ApplicationView.GetForCurrentView().Id;
});

await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newViewID, ViewSizePreference.UseMinimum);
}
}
}
}


这是我的MainPage.xaml:

<Page
x:Class="VideoSamplePlayer.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:VideoSamplePlayer"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

<Grid>
<Button Content="Open Video Output" HorizontalAlignment="Center" Margin="0,55,0,0" VerticalAlignment="Top" Height="52" Width="173" Click="Button_Click"/>

</Grid>
</Page>


这是我的VideoPlayer.xaml.cs:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Media.Core;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace VideoSamplePlayer
{
public sealed partial class VideoPlayer : Page
{
public VideoPlayer()
{
this.InitializeComponent();
}
private async void pickFileButton_Click(object sender, RoutedEventArgs e)
{

// Create and open the file picker
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.ViewMode = PickerViewMode.Thumbnail;
openPicker.SuggestedStartLocation = PickerLocationId.VideosLibrary;
openPicker.FileTypeFilter.Add(".mp4");
openPicker.FileTypeFilter.Add(".mkv");
openPicker.FileTypeFilter.Add(".avi");

StorageFile file = await openPicker.PickSingleFileAsync();
if (file != null)
{
mediaPlayerElement.MediaPlayer.Source = MediaSource.CreateFromStorageFile(file);
mediaPlayerElement.MediaPlayer.RealTimePlayback = true;
mediaPlayerElement.MediaPlayer.Play();
}
}
}
}


这是我的VideoPlayer.xaml:

<Page
x:Class="VideoSamplePlayer.VideoPlayer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:VideoSamplePlayer"
xmlns:mediacore="using:Windows.Media.Core"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

<Grid>
<StackPanel Orientation = "Vertical" >

<StackPanel Orientation="Horizontal">
<Button x:Name="pickFileButton" Content="Pick video" Margin="0,0,0,10" Click="pickFileButton_Click"/>
</StackPanel>
<MediaPlayerElement x:Name="mediaPlayerElement"
AutoPlay="False" Margin="5"
HorizontalAlignment="Stretch"
Height="300"
AreTransportControlsEnabled="True"/>
</StackPanel>
</Grid>
</Page>


我想将文件选择器按钮移到MainPage,但是VideoPlayer中仍然有视频输出。

我怎样才能做到这一点?

谢谢!

最佳答案

进行了一些尝试,但终于找到了解决方案!诀窍是使用自定义事件...而棘手的部分是我们正在使用多个线程(每个窗口都在其自己的线程中运行)。

基本上,我们将按钮及其处理程序移到MainPage,但在VideoPlayer页面上将与视频播放器交互的行保留。然后,我们需要声明一个自定义事件,该事件允许MainPage告诉VideoPlayer已选择了视频,并将选定的视频传递到VideoPlayer页面。最后,VideoPlayer页面可以为它包含的实际MediaPlayerElement设置源和详细信息,并实际播放视频。

让我们看一下每个部分:

首先在MainPage上声明您的自定义事件:

public delegate void VideoSelectedHandler(object sender, VideoSelectionArgs e);
public event VideoSelectedHandler VideoSelected;

private void RaiseVideoSelectedEvent(MediaSource source)
{
// Ensure that something is listening to the event.
if (this.VideoSelected != null)
{
// Create the args, and call the listening event handlers.
VideoSelectionArgs args = new VideoSelectionArgs(source);
this.VideoSelected(this, args);
}
}


您还需要声明事件参数的类(并且适当地,它从 EventArgs继承。您可以在同一文件(但在 MainPage类之外)或其他文件中声明它:

public class VideoSelectionArgs : EventArgs
{
public MediaSource Source { get; private set; }

public VideoSelectionArgs(MediaSource source)
{
this.Source = source;
}
}


接下来,我们需要 VideoPlayer页来订阅该事件,以便它监听正在引发的事件。将事件处理程序添加到 VideoPlayer页面:

public void VideoSelected(object sender, VideoSelectionArgs e)
{
mediaPlayerElement.MediaPlayer.Source = e.Source;
mediaPlayerElement.MediaPlayer.RealTimePlayback = true;
mediaPlayerElement.MediaPlayer.Play();
}


请注意,这是负责设置 MediaPlayerElement的代码,并且接受 MediaSource作为事件的参数。

接下来,让 VideoPlayer页面订阅 MainPage的事件。在 Button_Click上的 MainPage事件处理程序中,我们需要添加两行:

Frame newFrame = new Frame();
newFrame.Navigate(typeof(VideoPlayer), null);

// These are the two new lines... the others are shown for reference of where to place these.
VideoPlayer videoPlayerPage = newFrame.Content as VideoPlayer;
this.VideoSelected += videoPlayerPage.VideoSelected;

Window.Current.Content = newFrame;
Window.Current.Activate();
VideoPlayerWindow = Window.Current;


现在,您可以简单地从 pickFileButton_Click处理程序(现在在 MainPage上)调用此事件,然后传入从 MediaSource获得的 FileOpenPicker ...但是这会给您带来麻烦(并且我花了最长的时间找出来的东西)。

我们必须记住,每个窗口都在自己的线程上运行。即使您从另一个窗口调用代码,该代码仍在从其调用的线程上运行。这意味着,如果您仅执行上述操作,代码将编译并运行,但是当您尝试选择视频文件时,会出现运行时错误,并显示一条消息,指出资源已编组在另一个线程上。

解决方案是安排在与第二个窗口运行时相同的线程上获取视频文件的工作。因此,我们需要再进行两次修改才能完成此操作。

首先,我们有一个 Dispatcher的概念。每个控件都有一个。您已经使用了与新视图相关联的 Dispatcher(使用 var myView声明了该视图。需要使用相同的 Dispatcher来安排视频文件的工作,因此我们需要对其进行维护。只需添加一个属性到您的 MainPage

CoreApplicationView VideoPlayerView { get; set; }


并调整视图创建,以创建该属性的新视图,而不是 var myView

VideoPlayerView = CoreApplication.CreateNewView();

await VideoPlayerView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>



最后,我们可以设置 pickFileButton_Click处理程序。将您的按钮(按钮本身的XAML中不需要修改)移到您的 MainPage.xaml。然后将点击处理程序也移至MainPage,但进行以下两个修改:


替换引用 mediaPlayerElement的代码(现在位于 VideoPlayer页面上的自定义事件处理程序中)。通过致电引发自定义事件。
使用同一调度程序,将所有代码包装到另一个计划中,以在第二个窗口的线程上运行。


修改后的事件处理程序现在位于 MainPage上,如下所示:

private async void pickFileButton_Click(object sender, RoutedEventArgs e)
{
// Schedule the work here on the same thread as the VideoPlayer window,
// so that it has access to the file and MediaSource to play.
await this.VideoPlayerView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
// Create and open the file picker
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.ViewMode = PickerViewMode.Thumbnail;
openPicker.SuggestedStartLocation = PickerLocationId.VideosLibrary;
openPicker.FileTypeFilter.Add(".mp4");
openPicker.FileTypeFilter.Add(".mkv");
openPicker.FileTypeFilter.Add(".avi");

StorageFile file = await openPicker.PickSingleFileAsync();
if (file != null)
{
MediaSource sourceFromFile = MediaSource.CreateFromStorageFile(file);

// Raise the event declaring that a video was selected.
this.RaiseVideoSelectedEvent(sourceFromFile);
}
});
}


那应该做到的!我确实测试了代码,并使其成功运行并与计算机上的真实视频文件一起运行。

希望有帮助!

完整代码的最终形式如下:

MainPage.xaml.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel.Core;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Core;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace VideoSamplePlayer
{

public sealed partial class MainPage : Page
{
int newViewID = 0;

Window VideoPlayerWindow;

// To store the reference to the view control, so that it's dispatcher
// can be used to schedule more work on its thread.
CoreApplicationView VideoPlayerView { get; set; }

// The custom event declaration, to be raised when a media source for the video
// is selected.
public delegate void VideoSelectedHandler(object sender, VideoSelectionArgs e);
public event VideoSelectedHandler VideoSelected;

private void RaiseVideoSelectedEvent(MediaSource source)
{
// Ensure that something is listening to the event.
if (this.VideoSelected != null)
{
// Create the args, and call the listening event handlers.
VideoSelectionArgs args = new VideoSelectionArgs(source);
this.VideoSelected(this, args);
}
}

public MainPage()
{
this.InitializeComponent();

}

private async void Button_Click(object sender, RoutedEventArgs e)
{
if (newViewID == 0)
{
// Store the newly created view control.
this.VideoPlayerView = CoreApplication.CreateNewView();

await this.VideoPlayerView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
Frame newFrame = new Frame();
newFrame.Navigate(typeof(VideoPlayer), null);

// Have the new VideoPlayer page subscribe to the media source selection event on this page.
VideoPlayer videoPlayerPage = newFrame.Content as VideoPlayer;
this.VideoSelected += videoPlayerPage.VideoSelected;

Window.Current.Content = newFrame;
Window.Current.Activate();
VideoPlayerWindow = Window.Current;

newViewID = ApplicationView.GetForCurrentView().Id;
});

await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newViewID, ViewSizePreference.UseMinimum);
}
}

private async void pickFileButton_Click(object sender, RoutedEventArgs e)
{
// Schedule the work here on the same thread as the VideoPlayer window,
// so that it has access to the file and MediaSource to play.
await this.VideoPlayerView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
// Create and open the file picker
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.ViewMode = PickerViewMode.Thumbnail;
openPicker.SuggestedStartLocation = PickerLocationId.VideosLibrary;
openPicker.FileTypeFilter.Add(".mp4");
openPicker.FileTypeFilter.Add(".mkv");
openPicker.FileTypeFilter.Add(".avi");

StorageFile file = await openPicker.PickSingleFileAsync();
if (file != null)
{
MediaSource sourceFromFile = MediaSource.CreateFromStorageFile(file);

// Raise the event declaring that a video was selected.
this.RaiseVideoSelectedEvent(sourceFromFile);
}
});
}
}

// Class definition for the custom event args, which allows a
// media source to be passed to any event handlers that are listening.
public class VideoSelectionArgs : EventArgs
{
public MediaSource Source { get; private set; }

public VideoSelectionArgs(MediaSource source)
{
this.Source = source;
}
}
}


VideoPlayer.xaml.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Media.Core;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace VideoSamplePlayer
{
public sealed partial class VideoPlayer : Page
{
public VideoPlayer()
{
this.InitializeComponent();
}

// The event handler, which will listen for MainPage's VideoSelected
// event, after being subscribed to it on the MainPage.
public void VideoSelected(object sender, VideoSelectionArgs e)
{
// Get the MediaSource from the event arguments, and set up and start
// the media player.
mediaPlayerElement.MediaPlayer.Source = e.Source;
mediaPlayerElement.MediaPlayer.RealTimePlayback = true;
mediaPlayerElement.MediaPlayer.Play();
}
}
}


注意:此代码已通过在打开第二个窗口后单击“选择视频”按钮进行了测试。您可能需要做更多的工作,以确保在打开第二个窗口之前可以安全单击(或直接隐藏它直到打开第二个窗口)。

关于c# - 在第二个窗口中显示视频(UWP C#),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50916606/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com