当前位置: 首页 > article >正文

WPF MVVM如何在ViewModel直接操作控件对象

早些年在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  }

示例代码


http://www.kler.cn/a/288851.html

相关文章:

  • Kubernetes的基本构建块和最小可调度单元pod-0
  • 【缓存策略】你知道 Cache Aside(缓存旁路)这个缓存策略吗
  • 数据库管理-第260期 业务向前,数据库向后(20241111)
  • FPGA实现以太网(二)、初始化和配置PHY芯片
  • 鸿蒙多线程开发——并发模型对比(Actor与内存共享)
  • [CKS] Create/Read/Mount a Secret in K8S
  • 【数学建模国赛思路预约】2024高教社杯全国大学生数学建模竞赛助攻——思路、可运行代码、成品参考
  • 【数据结构】Set的使用与注意事项
  • 正则表达式实现括号替换
  • 【机器学习】CNN在计算机视觉中的应用
  • 数学建模学习(130):神经网络预测—模型选择与实战案例解析
  • LeetCode—string练习
  • etcdctl defrag 剔除、添加etcd节点
  • 调用k8s api实现添加用户并授权
  • 【Hot100】LeetCode—33. 搜索旋转排序数组
  • 台球助教APP小程序的前端交互设计
  • Redis的内存淘汰策略
  • 正则表达式实现带有条件的爬取
  • 动态规划-最大子数组和
  • [解决]Prometheus 与 Grafana进行组合,但是不显示数据与图像
  • 【王树森】Transformer模型(1/2): 剥离RNN,保留Attention(个人向笔记)
  • Java开发学习Kotlin 笔记
  • 每天学习一个基础算法之插入排序
  • 谷歌地图广告指南
  • P1438 无聊的数列
  • React 实现PDF预览(数据源使用文件流而不是url)