You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF/MVVM/Caliburn架构下WebView2自定义数据目录调用位置问题

Caliburn/MVVM架构WPF应用WebView2初始化问题解决方案

现有项目配置

Bootstrapper中ViewModel注册代码

builder.RegisterType<CustomWebViewModel>().As<Screen>();

CustomWebView.xaml中WebView2初始定义

<Grid>
    <wv2:WebView2 x:Name="WebView2" Source="{Binding WebAddress, Mode=OneWay, 
        UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True}" />
</Grid>

问题现象

开发环境下应用运行正常,WebView2可正确加载展示内容;生产环境应用安装在C:\Program Files\Company\Product\目录时,启动抛出错误:

Microsoft Edge can't read and write to its data directory: C:\Program Files\Company\Product\Product.exe.WebView2\EBWebView

故障根因

WebView2默认将用户数据目录创建在应用可执行文件同级目录下,普通用户无Program Files目录的写入权限,因此需要自定义具备读写权限的用户数据目录。已编写自定义环境初始化代码如下:

var appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var userDataFolder = System.IO.Path.Combine(appData, "CustomWebView2");

var env = await CoreWebView2Environment.CreateAsync(null, userDataFolder);
var webView2 = (WebView2)this.FindName("WebView2");
if (webView2 != null)
    await webView2.EnsureCoreWebView2Async(env);

重复初始化异常原因

此前在OnCoreWebView2InitializationCompleted、OnContentLoading事件中调用上述代码抛出如下异常:

System.ArgumentException: 'WebView2 was already initialized with a different CoreWebView2Environment. Check to see if the Source property was already set or EnsureCoreWebView2Async was previously called with different values.'

异常触发的核心原因是XAML中预先给WebView2设置了Source绑定,WebView2控件只要检测到Source属性被赋值,就会自动使用默认环境参数触发初始化,上述两个事件的触发时机都晚于自动初始化的执行节点,此时再传入自定义环境调用初始化方法,必然抛出重复初始化错误。

正确实现方式

  1. 首先修改XAML代码,移除WebView2的Source属性预先绑定,阻断控件自动初始化触发条件:
<Grid>
    <wv2:WebView2 x:Name="WebView2" />
</Grid>
  1. 将自定义环境初始化逻辑放在View的Loaded事件中执行(Caliburn.MVVM架构下可直接在View的code-behind中编写,不违反MVVM原则;若要严格规避code-behind可通过附加属性实现),初始化完成后再为WebView2赋值Source:
// CustomWebView.xaml.cs
private async void UserControl_Loaded(object sender, RoutedEventArgs e)
{
    // 避免Loaded事件多次触发重复初始化
    if (WebView2.CoreWebView2 != null) return;

    var appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
    var userDataFolder = Path.Combine(appData, "CustomWebView2");
    // 提前创建目录,避免极端情况下目录不存在引发异常
    Directory.CreateDirectory(userDataFolder);

    var webEnv = await CoreWebView2Environment.CreateAsync(null, userDataFolder);
    await WebView2.EnsureCoreWebView2Async(webEnv);

    // 初始化完成后再赋值页面地址,替代原有XAML绑定逻辑
    if (DataContext is CustomWebViewModel vm)
    {
        WebView2.Source = new Uri(vm.WebAddress);
    }
}

如果需要保留ViewModel驱动地址变更的能力,可在初始化完成后,监听ViewModel的WebAddress属性变更事件,同步更新WebView2的Source属性即可。

内容的提问来源于stack exchange,提问作者IgorStack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 22:09:49