On Windows Phone 8.1, I am using the Caliburn.Micro view-model-first approach, but as the view model cannot have any knowledge of the view, I cannot see how I can bind a MediaCapture object to a CaptureElement in the view.
-
They are both frameworkelements so they both can be bound, and to be clear you are talking about CaptureElement and MediaElement – mvermef May 29 '14 at 23:19
-
– mvermef May 29 '14 at 23:30
-
No, I am talking about the [MediaCapture object](http://msdn.microsoft.com/en-us/library/windowsphone/develop/windows.media.capture.mediacapture.aspx). In MVVM context, the CaptureElement lives in the View, while the MediaCapture object lives in the ViewModel. As the ViewModel should be completely agnostic about the View, how can the MediaCapture be bound as source? – Frederik Krautwald May 30 '14 at 07:22
-
MediaCapture it is the action to the event... is it not? – mvermef May 31 '14 at 04:04
-
MediaCapture is the class that gets instantiated to capture photos, audio, and video from the capture device. – Frederik Krautwald May 31 '14 at 09:01
4 Answers
I had the same problem. I'm using MVVM Light with Windows Phone 8.1 WinRT (Universal Apps).
I used ContentControl and binded to CaptureElement:
<ContentControl HorizontalAlignment="Left"
Width="320" Height="140" Content="{Binding CaptureElement}"/>
CaptureElement and MediaCapture are properties in my ViewModel:
private MediaCapture _mediaCapture;
public MediaCapture MediaCapture
{
get
{
if (_mediaCapture == null) _mediaCapture = new MediaCapture();
return _mediaCapture;
}
set
{
Set(() => MediaCapture, ref _mediaCapture, value);
}
}
private CaptureElement _captureElement;
public CaptureElement CaptureElement
{
get
{
if (_captureElement == null) _captureElement = new CaptureElement();
return _captureElement;
}
set
{
Set(() => CaptureElement, ref _captureElement, value);
}
}
And next I call ConfigureMedia() in ViewModel's constructor:
async void ConfigureMedia()
{
await MediaCapture.InitializeAsync();
CaptureElement.Source = MediaCapture;
await MediaCapture.StartPreviewAsync();
}
It's important to firstly initialize MediaCapture, next set Source and finally StartPeview. For me it works :)

- 836
- 16
- 23
-
My project was dropped long ago, so I cannot confirm if this would solve my issue. However, I will accept this as the answer. – Frederik Krautwald May 26 '15 at 22:45
-
Be aware, this may potentially lead to memory leak, because CaptureElement inherits from Controls, and using Controls in ViewModel (outside of viewtree) is not a good idea, as Control's finalizer may not be called. – Vitalii Vasylenko Jun 10 '15 at 10:21
If you're trying to keep strict view / view model separation then there are couple of possibilities.
Have you tried straight binding?
<CaptureElement Source="{Binding SomeMediaCapture}" />
If that doesn't work another one is create your own attached property that you could put on CaptureElement. When that property is set you can set the source yourself.
<CaptureElement custom:CaptureHelper.Source="{Binding SomeMediaCapture}" />
Here's a sample of doing some similar with web view and creating an html binding.
The way I tend to do this though is create an interface abstracting the view (say ICaptureView) that the view implements.
I can then cast the view held by the view model
var captureView = (ICaptureView) GetView();
where ICaptureView implements a SetCaptureSource method. This way it's still testable as you can attach a mock ICaptureView to the view model for testing.

- 10,549
- 1
- 28
- 31
-
1Directly binding the MediaCapture as source for CaptureElement is not possible as the MediaCapture requires to be initialized first. I have been doing exactly what you are proposing by creating a utility/helper class that creates a dependency property which registers a property by type of MediaCapture. However, this results in a very peculiar error when run: _WinRT information: Cannot deserialize XBF metadata property list as '%1' was not found in type '%0'._ It is similar to the [bug reported here](http://bit.ly/1m0gArt). – Frederik Krautwald May 31 '14 at 11:15
-
Could you initialise internally before setting to the bound property? Otherwise I'd go with the third option that I know works. – Nigel Sampson Jun 01 '14 at 21:25
-
@FrederikKrautwald Did you make progress on this? I'm facing the exact same issue. – Markus Bruckner Sep 02 '14 at 14:13
-
@MarkusBruckner Not any progress that solved the issue. I came to realize that either Microsoft or Caliburn has a problem, and I believe it’s Microsoft, which won’t let itself solve through a ViewModel-first approach. So the project got dropped. – Frederik Krautwald Sep 03 '14 at 23:23
Adding to Hawlett's answer, I had to do a little bit more to get the camera displaying correctly. I have changed ConfigureMedia() to be:
private async void ConfigureMedia()
{
_deviceInformationCollection = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
await MediaCapture.InitializeAsync(new MediaCaptureInitializationSettings
{
VideoDeviceId = _deviceInformationCollection[_deviceInformationCollection.Count - 1].Id
// The rear-facing camera is the last in the list
});
MediaCapture.VideoDeviceController.PrimaryUse = CaptureUse.Photo;
MediaCapture.SetPreviewRotation(VideoRotation.Clockwise90Degrees);
CaptureElement.Source = MediaCapture;
CaptureElement.Stretch = Stretch.UniformToFill;
await MediaCapture.StartPreviewAsync();
}

- 245
- 1
- 9
- 13