Search code examples
c#wpfxamlmvvmcefsharp

CefSharp with WPF MVVM


I am using CefSharp WPF control in my project with MVVM pattern. I have tried to show external URL inside Chromium browser. I have used LoadingStateChanged event to track the page load event inside the Chromium browser. I am getting the below error message while listening for LoadingStateChanged event. Could you please help me to resolve the issue?

Error Message:

The calling thread cannot access this object because a different thread owns it.

HomeControl.xaml:

<wpf:ChromiumWebBrowser WebBrowser="{Binding WebBrowser, Mode=OneWayToSource}" Address="{Binding Address, Mode=OneWay}">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="LoadingStateChanged">
            <i:InvokeCommandAction Command="{Binding Path=LoadingStateChangedCmd, Mode=OneWay}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</wpf:ChromiumWebBrowser>

HomeViewModel.cs:

public ICommand LoadingStateChangedCmd { get; set; }

public HomeViewModel() 
{
    LoadingStateChangedCmd = new CommunityToolkitInput.RelayCommand<LoadingStateChangedEventArgs>(LoadingStateChanged);
}

public void LoadingStateChanged(LoadingStateChangedEventArgs args)
{
    if (args.IsLoading == false)
    {
        Dispatcher.CurrentDispatcher.Invoke(() =>
        {
        });
    }
}

Detailed Error Message:

System.InvalidOperationException HResult=0x80131509 Message=The calling thread cannot access this object because a different thread owns it. Source=WindowsBase StackTrace: at System.Windows.Threading.Dispatcher.VerifyAccess() at System.Windows.DependencyObject.GetValue(DependencyProperty dp) at System.Windows.Interactivity.TriggerBase.get_Actions() at System.Windows.Interactivity.TriggerBase.InvokeActions(Object parameter) at System.Windows.Interactivity.EventTriggerBase.OnEvent(EventArgs eventArgs) at System.Windows.Interactivity.EventTriggerBase.OnEventImpl(Object sender, EventArgs eventArgs) at CefSharp.Wpf.ChromiumWebBrowser.CefSharp.Internals.IWebBrowserInternal.SetLoadingStateChange(LoadingStateChangedEventArgs args) at CefSharp.Internals.ClientAdapter.OnLoadingStateChange(ClientAdapter* , scoped_refptr* browser, Boolean isLoading, Boolean canGoBack, Boolean canGoForward)


Solution

  • You won't be able to do it that way, because the event is triggered on a worker thread and the Interaction framework calls dependency properties in response to it which aren't callable from another non-GUI thread.

    Handle the event in your view manually and do what needs to be done directly, even if it's just invoking a command in your VM.