【问题标题】:Take a snapshot of video in mediaelement without violating MVVM pattern在不违反 MVVM 模式的情况下拍摄 mediaelement 中的视频快照
【发布时间】:2015-09-28 20:03:48
【问题描述】:

我需要为 MediaElement 中播放的视频拍摄快照。

以下链接说明了我们如何实现这一目标。

http://www.thomasclaudiushuber.com/blog/2008/04/06/take-snapshots-of-videos-with-wpf/

但是如何在不违反 MVVM 模式的情况下做到这一点。

【问题讨论】:

  • 如果链接断开,您可能希望将该链接更多地总结到您的问题中,以供将来的读者参考

标签: wpf mvvm mediaelement


【解决方案1】:

我想说链接中的代码不违反 MVVM 模式...它使用代码隐藏,这在 MVVM 中不建议使用,但它不违反。

话虽如此,该代码在可重用的 UserControl 或自定义控件中会更好,通过事件、命令或 DependencyProperty 返回快照,以便您可以将其绑定到您的 ViewModel。

但总的来说,这更多的是一种良好做法,而不是 MVVM 要求。

<UserControl x:Class="SnapShots.SnapShotMediaViewer"
    xmlns=http://schemas.microsoft.com/winfx/2006/xaml/...
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Name="MediaViewer">
  <StackPanel>
   <MediaElement x:Name="media" Stretch="Fill" Height="200" Width="300">
      <MediaElement.Triggers>
       <EventTrigger RoutedEvent="MediaElement.Loaded">
        <BeginStoryboard>
         <Storyboard>
          <MediaTimeline Source="thomasOnBoard.wmv"
                         RepeatBehavior="Forever"/>
         </Storyboard>
        </BeginStoryboard>
       </EventTrigger>
      </MediaElement.Triggers>
     </MediaElement>
     <Button Click="Button_Click" Content="Snapshot"/>
  </StackPanel>
</UserControl>

例如,在代码隐藏中,通过事件公开快照。或者,如果您想在视图中完全避免代码隐藏或 EventTriggers,请使用 DependencyProperty。

public partial class SnapShotMediaViewer : UserControl
{
    public static readonly DependencyPropertyKey SnapshotPropertyKey =
        DependencyProperty.RegisterReadOnly("Snapshot", typeof(BitmapSource),
            typeof(SnapShotMediaViewer), new PropertyMetadata(null));

    public static readonly DependencyProperty SnapshotProperty =
        SnapshotPropertyKey.DependencyProperty;

    public BitmapSource Snapshot
    {
        get 
        {
            return (BitmapSource)GetValue(SnapshotProperty); 
        }
        private set
        {
            SetValue(SnapshotProperty, value);
        }
    }

    void Button_Click(object sender, RoutedEventArgs e)
    {
        Size dpi = new Size(96,96);
        RenderTargetBitmap bmp = 
            new RenderTargetBitmap(300, 200, 
            dpi.Width, dpi.Height, PixelFormats.Pbgra32);
        bmp.Render(media);

        Snapshot = bmp;
    }
}

然后只需将此控件添加到您的视图并创建一个绑定到Snapshot 属性。

【讨论】:

    【解决方案2】:
    <Button Command="{Binding TakeSnapshotCommand}" 
    CommandParameter="{Binding ElementName=media}"/>
    

    TakeSnapshotCommand 是一个实现 ICommand 的类,例如 RelayCommand。另外,您发送参数 T,在这种情况下,T 是 MediaElement,因此您将有以下声明。

    private RelayCommand<MediaElement> _takeSnapshotCommand;
    public RelayCommand<MediaElement> TakeSnapshotCommand
    {
    get{ return _takeSnapshotCommand ??(_takeSnapshotCommand = new RelayCommand<MediaElement>(YourMethodTakingMediaElementAsParameter));}
    }
    

    【讨论】:

    • 我不想将 mediaelement 传递给 viewmodel。我认为在 MVVM 模式中,不建议在视图模型中对 UI 组件进行操作。有什么办法可以让我只传递视频快照的位图图像作为命令参数。
    • 你可以通过任何你想要的。在 CommandParameter 中使用 Converter 来调整检索值。
    • 就目前而言,并不是真正的 MVVM。将元素转换为图像的绑定转换器,是的,这将是一个不错的设计。
    猜你喜欢
    • 1970-01-01
    • 2014-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-22
    • 2017-10-05
    • 1970-01-01
    相关资源
    最近更新 更多