WPF中如何将System.Windows.Controls转换为Windows.UI.Xaml.Controls类型
WPF项目集成UWP XAML控件相关问题解答
核心可行性结论
WPF项目完全可以调用UWP XAML控件,但无法通过直接类型强转的方式跨体系访问,所有跨框架的控件交互必须依赖官方提供的宿主组件做适配,不存在直接将System.Windows.Controls下的元素转换为Windows.UI.Xaml.Control类型的可行路径。
现有代码报错根因
- 当前代码中调用的
ElementCompositionPreview.GetElementVisual()属于UWP生态API,入参要求为Windows.UI.Xaml.DependencyObject类型,与传入的WPF侧StackPanel分属两套独立的运行时类型系统,没有兼容转换关系,就算手动加强制转换代码,运行时也会直接抛出类型转换无效异常 - 代码引用了错误命名空间下的同名称类,没有区分WPF自带合成API与UWP合成API的使用边界
正确实现流程
- 第一步:引入官方WPF侧UWP宿主组件,通过Nuget安装
Microsoft.Toolkit.Wpf.UI.XamlHost,这是微软提供的跨XAML框架适配组件,无需自行实现类型转换逻辑 - 第二步:在WPF XAML中引入宿主控件的命名空间,将需要承载的UWP控件通过
WindowsXamlHost声明在对应布局位置,参考代码片段:<!-- 顶部引入命名空间 --> xmlns:xamlHost="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost" <Grid> <StackPanel x:Name="AcrylicBackground" MinWidth="40"> <!-- 声明承载UWP控件的宿主 --> <xamlHost:WindowsXamlHost InitialTypeName="Windows.UI.Xaml.Controls.Border, Windows.UI.Xaml, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null" ChildChanged="AcrylicHost_ChildChanged"/> </StackPanel> <Grid Width="{Binding Width, ElementName=AcrylicBackground}" Background="Transparent"></Grid> </Grid> - 第三步:根据使用场景调整合成API的调用逻辑
- 如果是给WPF侧的元素加合成效果,需要引用
System.Windows.Media命名空间下的ElementCompositionPreview,调用GetElementVisual(panel)时传入WPF控件实例,此时不会触发类型报错 - 如果是需要操作宿主承载的UWP控件做亚克力效果,需要在
ChildChanged事件中获取初始化完成的UWP控件实例,再引用Windows.UI.Xaml.Hosting命名空间下的ElementCompositionPreview传入UWP实例做操作
private void AcrylicHost_ChildChanged(object sender, EventArgs e) { // 拿到宿主加载完成的UWP控件实例 var uwpControl = (sender as WindowsXamlHost).Child as Windows.UI.Xaml.Controls.Border; // 此时调用UWP侧的API不会触发类型转换错误 _compositor = Windows.UI.Xaml.Hosting.ElementCompositionPreview.GetElementVisual(uwpControl).Compositor; } - 如果是给WPF侧的元素加合成效果,需要引用
注意:两套XAML体系的类型是完全隔离的,不存在可以直接将WPF控件强转为UWP控件的实现方式,所有跨体系交互必须通过宿主组件中转
内容的提问来源于stack exchange,提问作者Meera
相关产品推荐
相关产品推荐

