C# 使用WindowsXamlHost覆盖托管CaptureElement
在我的WPF.NET Core 3.1应用程序中,我正试图在由C# 使用WindowsXamlHost覆盖托管CaptureElement,c#,wpf,.net-core,uwp,xaml-islands,C#,Wpf,.net Core,Uwp,Xaml Islands,在我的WPF.NET Core 3.1应用程序中,我正试图在由WindowsXamlHost托管的CaptureElement(摄像头提要)上覆盖一个Grid,但CaptureElement始终位于任何其他控件的顶部 无法在WindowsXamlHost/CaptureElement上覆盖网格吗 Î已经创建了一个示例应用程序。我需要CaptureElement,但还没有找到任何东西来捕获相机馈送并在其上方放置一些覆盖物 Xaml代码 <Window x:Class="SampleWPFXa
WindowsXamlHost
托管的CaptureElement
(摄像头提要)上覆盖一个Grid
,但CaptureElement
始终位于任何其他控件的顶部
无法在WindowsXamlHost/CaptureElement
上覆盖网格吗
Î已经创建了一个示例应用程序。我需要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>
视图模型
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));
}
}
public类主视图模型:PropertyChangedWare
{
公共主视图模型()
{
GetUwpCaptureElement();
}
私有媒体捕获(MediaCapture);;
公共媒体捕获媒体捕获{
得到{
如果(_mediaCapture==null)
_mediaCapture=新的mediaCapture();
返回媒体捕获;
}
设置{
_mediaCapture=价值;
OnPropertyChanged(名称为(MediaCapture));
}
}
公共CaptureElement CaptureElement{get;set;}
公共WindowsXamlHost XamlHostCaptureElement{get;set;}
///
///创建/承载UWP CaptureElement
///
私有void GetUwpCaptureElement()
{
XamlHostCaptureElement=新窗口XamlHost
{
InitialTypeName=“Windows.UI.Xaml.Controls.CaptureElement”
};
XamlHostCaptureElement.ChildChanged+=XamlHost_ChildChangedAsync;
}
私有异步void XamlHost_ChildChangedAsync(对象发送方,事件参数e)
{
var windowsXamlHost=(windowsXamlHost)发送方;
var capturelement=(capturelement)windowsXamlHost.Child;
CaptureElement=CaptureElement;
capturelement.Stretch=Windows.UI.Xaml.Media.Stretch.UniformToFill;
尝试
{
等待StartPreviewSync();
}
捕获(例外)
{
}
}
专用异步任务StartPreviewSync()
{
尝试
{
等待MediaCapture.InitializeAsync();
}
捕获(未经授权的访问例外)
{
//_logger.Info($“应用程序被拒绝访问摄像头\n{ex}”);
返回;
}
尝试
{
capturelement.Source=MediaCapture;
等待MediaCapture.StartPreviewSync();
}
捕获(System.IO.FileLoadException ex)
{
System.Diagnostics.Debug.WriteLine(例如ToString());
}
}
}
公共类PropertyChangedWare:INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
受保护的虚拟void OnPropertyChanged([CallerMemberName]字符串propertyName=null)
{
PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(propertyName));
}
}
无法在WindowsXamlHost/CaptureElement上覆盖网格吗
不可以。就像WindowsFormsHost
中的Windows窗体控件一样,WindowsXamlHost
托管在单独的HWND中,该HWND始终绘制在WPF元素的顶部
从:
托管的Windows窗体控件在单独的HWND中绘制,因此它始终绘制在WPF元素的顶部
有一个类似的问题和一些可用的答案。我在尝试使用XAML Islands在WPF应用程序中托管
CaptureElement
时遇到了同样的问题。正如mm8所说,问题在于WPF将在任何WPF元素之后绘制WindowsXamlHost
但是,如果您只是试图将TextBlock
之类的内容覆盖在capturelement
上,则有一个快速解决此问题的方法。只需托管一个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>