Im trying to overlay a Grid
on top of CaptureElement
(Camera Feed) hosted with WindowsXamlHost
in my WPF .NET Core 3.1 App, but the CaptureElement
always stays on top of any other control.
Is it not possible to overlay a grid on top of WindowsXamlHost/CaptureElement
?
Î have created a Sample Application https://github.com/ValonK/SampleWPFXamlHost. I need the CaptureElement
and haven't found anything to capture camera feed and put some overlays above them.
Xaml Code
<Window x:Class="SampleWPFXamlHost.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SampleWPFXamlHost"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid Height="200"
Width="200"
Background="Red"/>
<ContentControl HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
Content="{Binding XamlHostCaptureElement}"/>
</Grid>
</Window>
ViewModel
public class MainViewModel : PropertyChangedAware
{
public MainViewModel()
{
GetUwpCaptureElement();
}
private MediaCapture _mediaCapture;
public MediaCapture MediaCapture {
get {
if (_mediaCapture == null)
_mediaCapture = new MediaCapture();
return _mediaCapture;
}
set {
_mediaCapture = value;
OnPropertyChanged(nameof(MediaCapture));
}
}
public CaptureElement CaptureElement { get; set; }
public WindowsXamlHost XamlHostCaptureElement { get; set; }
/// <summary>
/// Create / Host UWP CaptureElement
/// </summary>
private void GetUwpCaptureElement()
{
XamlHostCaptureElement = new WindowsXamlHost
{
InitialTypeName = "Windows.UI.Xaml.Controls.CaptureElement"
};
XamlHostCaptureElement.ChildChanged += XamlHost_ChildChangedAsync;
}
private async void XamlHost_ChildChangedAsync(object sender, EventArgs e)
{
var windowsXamlHost = (WindowsXamlHost)sender;
var captureElement = (CaptureElement)windowsXamlHost.Child;
CaptureElement = captureElement;
CaptureElement.Stretch = Windows.UI.Xaml.Media.Stretch.UniformToFill;
try
{
await StartPreviewAsync();
}
catch (Exception)
{
}
}
private async Task StartPreviewAsync()
{
try
{
await MediaCapture.InitializeAsync();
}
catch (UnauthorizedAccessException ex)
{
//_logger.Info($"The app was denied access to the camera \n {ex}");
return;
}
try
{
CaptureElement.Source = MediaCapture;
await MediaCapture.StartPreviewAsync();
}
catch (System.IO.FileLoadException ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
}
}
}
public class PropertyChangedAware : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Is it not possible to overlay a grid on top of WindowsXamlHost/CaptureElement?
No. Just like a Windows Forms control in a WindowsFormsHost
, a WindowsXamlHost
is hosted in a separate HWND that is always drawn on top of the WPF elements.
From the docs:
A hosted Windows Forms control is drawn in a separate HWND, so it is always drawn on top of WPF elements.
There is a similar question with some answers available here.