早些年在WPF中使用COM组件时,需要在ViewModel中操作COM组件中的控件对象,但是这个控件对象又不支持绑定,
后面的解决办法是在窗口加载时,将控件对象以参数传递到Loaded事件的处理命令中,然后将这个对象记录下来,后面就可以直接操作这个控件了。
今天同事在使用WebView2的时候,又遇到这个问题,写个文章分享一下,给后续需要的小伙伴提供点参考。
我们创建一个WPF的项目,然后在界面上放置一个WMP控件(Windows Media Player)。
MainWindow.xaml
1 <Window x:Class="GetControlInViewModel.MainWindow"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6 xmlns:wmp="clr-namespace:AxWMPLib;assembly=AxInterop.WMPLib"
7 xmlns:local="clr-namespace:GetControlInViewModel"
8 mc:Ignorable="d"
9 Title="MainWindow" Height="450" Width="800">
10 <Grid>
11 <WindowsFormsHost>
12 <wmp:AxWindowsMediaPlayer x:Name="WMPPlayer"></wmp:AxWindowsMediaPlayer>
13 </WindowsFormsHost>
14 </Grid>
15 </Window>
如果我们想在ViewModel中操作这个WMP对象,可以在Loaded事件中添加如下处理
这里我使用了废弃的包MvvmLight来做演示,因为比较简单方便。
1 <i:Interaction.Triggers>
2 <i:EventTrigger EventName="Loaded">
3 <i:InvokeCommandAction Command="{Binding LoadedCommand}" CommandParameter="{Binding ElementName=WMPPlayer}"></i:InvokeCommandAction>
4 </i:EventTrigger>
5 </i:Interaction.Triggers>
ViewModel
1 public class MainViewModel : ViewModelBase
2 {
3 private AxWMPLib.AxWindowsMediaPlayer mediaPlayer;
4
5 public RelayCommand<AxWMPLib.AxWindowsMediaPlayer> OnLoadedCommand { get; private set; }
6
7 public MainViewModel()
8 {
9 OnLoadedCommand = new RelayCommand<AxWMPLib.AxWindowsMediaPlayer>(OnLoaded);
10 }
11
12 private void OnLoaded(AxWMPLib.AxWindowsMediaPlayer axWindowsMediaPlayer)
13 {
14 this.mediaPlayer = axWindowsMediaPlayer;
15 }
16 }
然后将ViewModel绑定到MainWindow上,运行时就可以获取到WMP对象
有时我们会遇到控件未初始化,在Loaded事件中无法获取到控件对象,类似下面这样
比如在使用Prism进行区域导航的时候,就可能会出现这个问题。
此时我们可以将整个窗口/用户控件(UserControl)传过来,然后延时一秒,或者延时加循环几次,就可以获取到控件对象
1 private async void OnLoaded(Window window)
2 {
3 await Task.Delay(1000);
4 var webViewElement = window.FindName("WebView");
5 if (webViewElement != null)
6 this.webView = webViewElement as WebView2;
7 }