Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I recently ran into the same problem. It seems that binding the video source is quite tricky, because you need to initialise, set and start the preview stream in the right order. I fixed the issue using an attached property:</p> <pre><code>/// &lt;summary&gt; /// This utility class provides an attached property that enables us to /// bind the source of a &lt;see cref="CaptureElement"/&gt;. /// &lt;/summary&gt; public static class VideoSourceBinding { public static MediaCapture GetVideoSource(DependencyObject obj) { return (MediaCapture) obj.GetValue(VideoSourceProperty); } public static void SetVideoSource(DependencyObject obj, MediaCapture value) { obj.SetValue(VideoSourceProperty, value); } public static readonly DependencyProperty VideoSourceProperty = DependencyProperty.RegisterAttached("VideoSource", typeof(MediaCapture), typeof(VideoSourceBinding), new PropertyMetadata(null, onVideoSourcePropertyChanged)); private static async void onVideoSourcePropertyChanged( DependencyObject d, DependencyPropertyChangedEventArgs e) { Debug.Assert(d is CaptureElement); Debug.Assert(e.Property == VideoSourceBinding.VideoSourceProperty); CaptureElement preview = d as CaptureElement; if (d != null) { if (preview.Source != null) { // If another camera was attached before, stop it. await preview.Source.StopPreviewAsync(); } try { preview.Source = (MediaCapture) e.NewValue; } catch { // The property change occurred before the the video source // was properly initialised. In this case, we ignore the // change and wait for the source to fire the event again // once the initialisation was completed. // Important: The source must actually change in order for // the event to be fired (the attached property will detect // if the same object was re-set) and ignore this. preview.Source = null; } if (preview.Source != null) { // Start the preview stream. await preview.Source.StartPreviewAsync(); } } } } </code></pre> <p>The video source is then bound like this:</p> <pre><code>&lt;CaptureElement u:VideoSourceBinding.VideoSource="{Binding VideoCapture}" /&gt; </code></pre> <p>Note that the order in which you do things in the view model is important:</p> <pre><code>public class ViewModel : Screen { // Note: The sample uses a Caliburn Micro base class - this is, however, not // a requirement. public MediaCapture VideoCapture { get; private set; } /// &lt;summary&gt; /// Starts the video preview. /// &lt;/summary&gt; /// &lt;remarks&gt; /// Call this method whenever it is necessary to (re-) start the preview, eg /// if the page is activated or if the settings have changed. /// &lt;/remarks&gt; private async void startVideo() { var captureSettings = new MediaCaptureInitializationSettings() { StreamingCaptureMode = StreamingCaptureMode.Video }; // Set a NEW MediaCapture! Do not re-use the old one, because the property // change event of the attached property will not fire otherwise. this.VideoCapture = new MediaCapture(); await this.videoCapture.InitializeAsync(captureSettings); // Notify the UI about a new video source AFTER the initialisation completed. It // is important to await the initialisation here. this.NotifyOfPropertyChange(() =&gt; this.VideoCapture); } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload