CefSharp Wpf Missing Method - c#

I'm working on this plugin for Rhino (a 3D modelling software) that opens a web page, therefore I'm trying to use CefSharp in a WPF window.
As a simple proof of concept right now I'm just trying to open a browser that will show Google. Super simple, but not working as I keep getting this error:
System.MissingMethodException: 'Method not found: 'Void CefSharp.IFrameHandler.OnFrameAttached(CefSharp.IWebBrowser, CefSharp.IBrowser, CefSharp.IFrame)'.'
My window:
<Window x:Class="UI.PrototypeBrowser"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:wpf="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"
mc:Ignorable="d"
Title="PrototypeBrowser" Height="450" Width="800">
<Grid>
<wpf:ChromiumWebBrowser x:Name="Browser" Address="www.google.com"/>
</Grid>
</Window>
And the code behind:
public partial class PrototypeBrowser : Window
{
public PrototypeBrowser()
{
InitializeComponent();
Cef.Initialize(new CefSettings());
}
}
The Rhino command that calls the WPF window (not sure if it's useful):
protected override Result RunCommand(RhinoDoc doc, RunMode mode)
{
PrototypeBrowser browser = new PrototypeBrowser();
browser.ShowDialog();
return Result.Success;
}
And this is thelist of packages I'm using in my solution:
What am I doing wrong?
Thanks for the help!

Related

Generic Window-Classes

I want to have a generic type of a Window.
However, if I implement the <R> into the class definition, it gives me errors, everywhere I reference on the xaml, e.g. at InitializeComponent(); or if I want to access any label or button.
The name 'InitalizeComponent' is not available in the current context
Probably, the reference/linking from the xaml to the code behind does not work properly.
Are there any suggestions, how I can achieve a correct linking to the xaml with generic window classes?
C#
namespace MyNamespace
{
public partial class Designer<R> : Window, IEventListener
where R : Region, new()
{
...
}
}
XAML
<Window
x:Class="MyNamespace.Designer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MyNamespace"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="Designer"
Width="1600"
Height="1000"
mc:Ignorable="d">
...
</Window>
You need to provide x:TypeArguments directive:
<Window
x:Class="MyNamespace.Designer"
x:TypeArguments="src:Region"
...
</Window>

Adding resources to an instance of WPF window

I'm making an AutoCAD .net program that has a WPF window as the interface. Currently the WPF interface is being referenced into the AutoCAD .net aplication and I'm calling the window from AutoCAD as follows.
public class Class1
{
public static WPFWindow.MainWindow mainWindow = new WPFWindow.MainWindow();
[CommandMethod("Launch", CommandFlags.Session)]
public void Launch()
{
Autodesk.AutoCAD.ApplicationServices.Application.ShowModalWindow(mainWindow);
}
}
This works fine until I start adding any form of resource to the WPF window I'm adding in. eg The following works until
<Window x:Class="WPFWindow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPFWindow"
mc:Ignorable="d"
Title="Test" Height="450" Width="800"
WindowStyle="None"
AllowsTransparency="True"
>
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Themes/Styles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Button Content="Press Me"/>
</Grid>
....I reference a static resource style for the window
WindowStyle="None"
AllowsTransparency="True"
Style="{StaticResource MainWindow}"
>
With the static resource when I run the "Launch" command in AutoCAD the program fails to find the static resource. I'm unsure how to get the instance of the WPFWindow to find the resource using C# code. As a test I added the WPFWindow as a reference to a WPF application and managed to get it to find the resource using the Pack URI
<ResourceDictionary Source="pack://application:,,,/WPFWindow;component/Themes/Styles.xaml"/>
Is there a C# equivalent of that I can use for the instance of the WPFWindow.MainWindow?
I managed to get it to work by adding the resources to the window I was referencing in its code behind files.
namespace WPFWindow
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
this.Resources.Source = new Uri(#"pack://application:,,,/WPFWindow;component/Themes/Styles.xaml"", UriKind.Absolute);
InitializeComponent();
}
}
}
I think this allowed the static resources to be loaded in before they were called for the window.
You cant use Staticresource in the root tag for external Resourcedictionaries. At time of Initialization the resource is not present. Linking it in ctor before calling InitializeComponent (as you did) does actually the same...
...
WindowStyle="None"
AllowsTransparency="True"
Style="{DynamicResource MainWindow}"
...
will work.

cefsharp solution with multiple projects doesn't work

I have a solution with multiple projects.
The principle project is a WinFormsApplication that references a WPF project. I have tried to incorporate a WPF UserControl (defined in the WPF project) that contains CefSharp ChromiumWebBrowser in a Form using ElementHost.
public partial class WebForm : Form
{
private ElementHost elementHostWeb;
public WebForm()
{
InitializeComponent();
elementHostWeb = new ElementHost();
elementHostWeb.Height = this.Height;
elementHostWeb.Width = this.Width;
elementHostWeb.Child = new WebWPFUserControl();
}
}
WPF UserControl:
<UserControl x:Class="WpfApplication.WebWPFUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication"
xmlns:cefSharp="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"
mc:Ignorable="d"
Title="WebWPFUserControl" Height="350" Width="525">
<Grid>
<cefSharp:ChromiumWebBrowser Grid.Row="0"
Address="https://github.com/cefsharp/CefSharp/wiki/Frequently-asked-questions" />
</Grid>
When I tray to open the Form I get the following error:

Implementing own ViewModelLocator

I wanted to implement ViewModelLocator by my own. So I implemented the simplest app in the world. I did everything as in this tutorial. But I'm still getting an exception:
XamlParseException occured
Exception thrown: 'System.Windows.Markup.XamlParseException' in
PresentationFramework.dll
Additional information: 'Provide value on
'System.Windows.StaticResourceExtension' threw an exception.' Line
number '8' and line position '9'.
This is this line:
DataContext="{Binding MainWindowViewModel, Source={StaticResource ViewModelLocator}}">
Here is the code:
App.xaml
<Application x:Class="ViewModelLocatorDemo.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModelLocatorDemo="clr-namespace:ViewModelLocatorDemo">
<Application.Resources>
<viewModelLocatorDemo:ViewModelLocator x:Key="ViewModelLocator"/>
</Application.Resources>
</Application>
App.xaml.cs
namespace ViewModelLocatorDemo
{
using System.Windows;
using ViewModelLocatorDemo.Views;
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
MainWindow mainWindow = new MainWindow();
mainWindow.Show();
}
}
}
ViewModelLocator.cs
namespace ViewModelLocatorDemo
{
using ViewModels;
public class ViewModelLocator
{
public MainWindowViewModel MainWindowViewModel
{
get { return new MainWindowViewModel(); }
}
}
}
MainWindow.xaml
<Window x:Class="ViewModelLocatorDemo.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="300" Width="300"
DataContext="{Binding MainWindowViewModel, Source={StaticResource ViewModelLocator}}">
<Grid>
<Frame x:Name="MainFrame" Margin="50" BorderThickness="2" BorderBrush="Black" />
</Grid>
</Window>
MainWindowViewModel.cs
namespace ViewModelLocatorDemo.ViewModels
{
public class MainWindowViewModel
{
public string MainText { get; set; }
public MainWindowViewModel()
{
MainText = "The first page";
}
}
}
In this answer I found:
Make sure that the resources are defined before the usage (in Xaml
parsing order). The easiest way is to place it into App.xaml
So I have it in App.xaml. If somebody would me explain what's going on here? Why am I getting this error?
You are running into this bug WPF - App.xaml file does not get parsed if my app does not set a StartupUri?
From that page:
There's a VS code generation bug where the code necessary to connect to the rest of the program sometimes is not inserted when contains only one entry and does not have a StartupUri attribute.
From that page, there are 3 solutions (summarizing here for completeness):
Add x:Name="App"
Add more resources in App.xaml like <viewModelLocatorDemo:ViewModelLocator x:Key="ViewModelLocator"/> and <viewModelLocatorDemo:ViewModelLocator x:Key="ViewModelLocator2"/>
Rather than overriding OnStartup, try using an event instead, Startup="Application_Startup"
This was definitely not obvious, and was difficult to troubleshoot and even find an answer for in my own search. Hopefully this answer will help others find the other answer.

Adding UserControl from one window to the MainWindow

I have a Mainwindow and a groupbox inside it.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="WpfApplication1.MainWindow"
Title="MainWindow"
Height="600" Width="800">
<Grid x:Name="MainGrid">
<GroupBox Header="Diagram Design" Name="gbDiagDesign">
</GroupBox>
</Grid>
</Window>
A simple UserControl
<UserControl x:Class="WpfApplication1.Controls.EntityControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="100" d:DesignWidth="100">
<Grid>
<Button x:Name="btn_show" Content="show me" />
</Grid>
</UserControl>
and another window with an OK button in it,
the question is how do I add the UserControl to the Groupbox in the MainWindow after I press the OK button.
public partial class NewEntity
{
public NewEntity()
{
InitializeComponent();
}
private void OK_Click(object sender, RoutedEventArgs e)
{
EntityControl entcon = new EntityControl();
**MainWindow.gbDiagDesign.Children.Add(**
}
the last row gives me an error, "an object reference is required for the nonstatic field.."
You can access MainWindow using Application.Current.MainWindow but it will return instance of Window class. Typecasting is required to convert it to actual class instance i.e. MainWindow.
This should work:
((MainWindow)Application.Current.MainWindow).gbDiagDesign.Add(entcon);
WPF is meant to be programmed using the MVVM pattern. If you do it another way, you will have to fight WPF all along instead of using it's great power. If you insist on doing it the other way, at least make the compiler happy:
MainWindow is a instance variable of your application class. You are not inside your application class, so you need an instance of your application class first to access MainWindow. You will also need to cast it to your Window type.

Categories