Размещение CaptureElement с наложением WindowsXamlHost
Я пытаюсь наложить Grid
на вершине CaptureElement
(Camera Feed) размещено на WindowsXamlHost
в моем приложении WPF .NET Core 3.1, но CaptureElement
всегда остается поверх любого другого элемента управления.
Нельзя ли наложить сетку поверх WindowsXamlHost/CaptureElement
?
Î создали образец приложения https://github.com/ValonK/SampleWPFXamlHost. мне нужноCaptureElement
и не нашли ничего, что можно было бы захватить с камеры и надеть над ними.
Код Xaml
<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));
}
}
2 ответа
Нельзя ли наложить сетку поверх WindowsXamlHost/CaptureElement?
Нет. Как и элемент управления Windows Forms в WindowsFormsHost
, а WindowsXamlHost
размещается в отдельном HWND, который всегда рисуется поверх элементов WPF.
Из документов:
Размещенный элемент управления Windows Forms рисуется в отдельном HWND, поэтому он всегда отображается поверх элементов WPF.
Есть аналогичный вопрос, некоторые ответы на который доступны здесь.
Я столкнулся с этой же проблемой, когда пытался разместить внутри своего приложения WPF с помощью островов XAML. Как сказал mm8, проблема в том, что WPF будет рисовать WindowsXamlHost после любого из элементов WPF.
Но есть быстрое решение этой проблемы, если вы просто пытаетесь наложить такие вещи, как
TextBlock
над вашим. Просто разместите пользовательский элемент управления UWP вместо размещения
CaptureElement
напрямую. Используя MVVM, вы можете передать текст из приложения WPF в пользовательский элемент управления UWP, и он отобразится.
Пример:
<UserControl
x:Class="MyUwpApp.MyUserControl1"
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">
<Grid>
<CaptureElement x:Name="captureElement"/>
<TextBlock Text="{Binding MyText}" Foreground="Yellow" FontSize="64" VerticalAlignment="Bottom" HorizontalAlignment="Left" Margin="15"/>
</Grid>
</UserControl>