繁体   English   中英

如何动态更改我在 MVVM XAML 中使用的控件

[英]How can I dynamically change what control I'm using within MVVM XAML

我正在编写一个使用 VLC 播放视频的简单应用程序。 这通常是一个简单的解决方案,但目前几乎所有的 VLC 库都有副作用; Vlc.DotNet.WPF 很棒,但它有一个副作用,它是 CPU 密集型的,但解决了分层视频的问题,而 LibVLCSharp.WPF 在 CPU 利用率方面要好得多,但在分层视频方面存在问题(空域问题)。 因此,我希望能够构建我的应用程序以允许我切换我使用哪个视频库来播放视频,以便我可以根据我的硬件和情境要求来管理两个渲染器的权衡。

每个库都提供了一个自定义用户控件,用于在视图中显示视频。 LibVLCSharp 提供LibVLCSharp.WPF.VideoView和 Vlc.DotNet.WPF 提供Vlc.DotNet.Wpf.VlcControl

我已经构建了我的代码以通过以下方式独立显示其中的每一个:

控制 Class 以使用 VlcDotNetWpf:

public class vlcPlayerDotNet : Vlc.DotNet.Wpf.VlcControl
{
   public vlcPlayerDotNet() {}
   ~vlcPlayerDotNet()
   {
      // class-specific cleanup routines
   }

   public void PlayVideo()
   {
      // class-specific video playback code to play Source video
   }

   // Dependency Properties
   public static readonly DependencyProperty SourceProperty =
      DependencyProperty.Register(
      "Source", typeof(string),
      typeof(vlcPlayerDotNet)
   );
   public string Source
   {
      get { return (string)GetValue(SourceProperty); }
      set { SetValue(SourceProperty, value); }
   } 

   /*
      ... and so on, for multiple dependency properties
   */
}

并控制 class 使用 LibVlcSharp.Wpf:

public class vlcPlayerLibVLCSharp : LibVLCSharp.WPF.VideoView
{
   public vlcPlayerLibVLCSharp() {}
   ~vlcPlayerLibVLCSharp()
   {
      // class-specific cleanup routines
   }

   public void PlayVideo()
   {
      // class-specific video playback code to play Source video
   }

   // Dependency Properties
   public static readonly DependencyProperty SourceProperty =
      DependencyProperty.Register(
      "Source", typeof(string),
      typeof(vlcPlayerLibVLCSharp)
   );
   public string Source
   {
      get { return (string)GetValue(SourceProperty); }
      set { SetValue(SourceProperty, value); }
   } 

   /*
      ... and so on, for multiple dependency properties
   */
}

在我的 ViewModel 中,我有一些需要的输入,即:

   private string animationFile;
   public string AnimationFile
   {
      get { return animationFile; }
      set { SetProperty(ref animationFile, value); }
   }

然后,在我的视图中,我定义了我想要使用的视频控件 - 例如,如果我使用的是 LibVLCSharp 播放器,我使用以下内容:

   <Grid>
      <local:vlcPlayerLibVLCSharp 
         Grid.Column="0" Grid.Row="0"                 
         HorizontalAlignment="Center" VerticalAlignment="Center" 
         Height="720" Width="1280"
         Source="{Binding AnimationFile}" LoadedBehavior="Play"  
         MediaEnded="animationPlayer_MediaEnded" 
         MediaFailed="animationPlayer_MediaFailed" 
         x:Name="vlcPlayer"/>
   </Grid>

其他玩家依此类推。

我不想要的是堆叠和折叠两个 View UserControl; 我希望能够在视图中拥有一个视图用户控件,并能够动态选择视图中实际使用的用户控件。 我的目标是有一个简单的视图,如果我以后可以在不更改视图的情况下添加另一个控件,那就太棒了(但这不是一个破坏者)。

我已经调查在视图中使用ContentControl来包含视频 UserControl,但我无法弄清楚如何处理需要传递给控件的依赖属性。 我还查看了DataTemplateDataTemplateSelector ,但我发现的所有示例都处理列表框,我很难从列表框到这些派生控件的概念飞跃。

任何关于如何构建我的代码以允许在引擎盖下进行交换的建议都值得赞赏!

您可以使用内容控件和数据模板

在您的父级 window 中定义每个视频播放器的数据模板。

<Window ...
        ...>

    <Window.Resources>
        <DataTemplate DataType="{x:Type viewModels:LibSharpViewModel}">
            <views:LibSharpView/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type viewModels:VlcViewModel}">
            <views:VlcView/>
        </DataTemplate>

    </Window.Resources>

    <Grid>        
        <ContentControl  Content="{Binding SelectedVideoPlayerViewModel}"/>               
    </Grid>
</Window>

然后在单独的 xaml 文件中定义 Vlc 和 LibSharp 视图。

您可以为视频播放器视图模型创建基本 class,这些视图模型定义了 Vlc 和 LibSharp VM 将从中继承的所需依赖项属性。

在父窗口的 VM 中,您可以根据您的硬件条件确定使用哪个播放器,并设置 SelectedVideoPlayerViewModel 以切换在内容控件中显示哪个控件。

暂无
暂无

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

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