将 System.Windows.Forms.WebBrowser 添加到 System.Windows.Controls.StackPanel 无法转换为 System.Windows.UIElement

Adding System.Windows.Forms.WebBrowser to System.Windows.Controls.StackPanel cannot convert to System.Windows.UIElement

我需要将 WebBrowser 控件添加到 WPF 应用程序中动态生成的 Window

基本上,当代理点击 link 时,我需要打开 webbrowser window,它在某些页面上禁用(或隐藏)了关闭 (X) 按钮,而在其他页面上则没有.原因是他们被重定向到收集付款的第 3 方支付系统,如果他们在收集付款后关闭浏览器 window 但在他们被重定向回我们的系统之前,我们不会在第 3 方收费时收到正在收集付款的通知我们的客户。

最初网络浏览器 window 是在 Windows.Form 中打开的,但我无法找到禁用 Form 上的 X 的方法,因此想切换到 WPF Window 因为我们的应用程序首先是 WPF,所以我引入了 window 和面板,但是现在当动态添加 WebBrowser 控件到面板 Children 时,它给出了以下错误

Error cannot convert from 'Desktop.ViewModels.PaymentViewModel.NavigateToTakePaymentCommand.MyWebBrowser' to 'System.Windows.UIElement'

private void OpenBrowser(PaymentViewModel viewModel, Uri uri)
{
   viewModel.BrowserWindow = new WithoutCloseButton();
   viewModel.BrowserWindow.Closed += BrowserWindow_Closed;
   var browser = new MyWebBrowser();
   var stackPanel = new StackPanel { Orientation = System.Windows.Controls.Orientation.Vertical };
  stackPanel.Children.Add(browser); // this bit fails
  viewModel.BrowserWindow.Content = stackPanel;

...

public class WithoutCloseButton : Window
{
    private const int GWL_STYLE = -16;
    private const int WS_SYSMENU = 0x80000;
    [DllImport("user32.dll", SetLastError = true)]
    private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
    [DllImport("user32.dll")]
    private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
}

public class MyWebBrowser : System.Windows.Forms.WebBrowser
{
    public static Guid IID_IHttpSecurity
        = new Guid("79eac9d7-bafa-11ce-8c82-00aa004ba90b");
    public static Guid IID_IWindowForBindingUI
        = new Guid("79eac9d5-bafa-11ce-8c82-00aa004ba90b");
    public const int S_OK = 0;
    public const int S_FALSE = 1;
    public const int E_NOINTERFACE = unchecked((int)0x80004002);
    public const int RPC_E_RETRY = unchecked((int)0x80010109);
    protected override WebBrowserSiteBase CreateWebBrowserSiteBase()
    {
        return new MyWebBrowserSite(this);
    }

    class MyWebBrowserSite : WebBrowserSite, UCOMIServiceProvider,IHttpSecurity, IWindowForBindingUI
    {
        private MyWebBrowser myWebBrowser;
        public MyWebBrowserSite(MyWebBrowser myWebBrowser) : base(myWebBrowser)
        {
            this.myWebBrowser = myWebBrowser;
        }

        public int QueryService(ref Guid guidService, ref Guid riid, out IntPtr ppvObject)
        {
            if (riid == IID_IHttpSecurity)
            {
                ppvObject = Marshal.GetComInterfaceForObject(this
                    , typeof(IHttpSecurity));
                return S_OK;
            }
            if (riid == IID_IWindowForBindingUI)
            {
                ppvObject = Marshal.GetComInterfaceForObject(this
                    , typeof(IWindowForBindingUI));
                return S_OK;
            }
            ppvObject = IntPtr.Zero;
            return E_NOINTERFACE;
        }

        public int GetWindow(ref Guid rguidReason , ref IntPtr phwnd)
        {
            if (rguidReason == IID_IHttpSecurity || rguidReason == IID_IWindowForBindingUI)
            {
                phwnd = myWebBrowser.Handle;
                return S_OK;
            }
            else
            {
                phwnd = IntPtr.Zero;
                return S_FALSE;
            }
        }

        public int OnSecurityProblem(uint dwProblem)
        {
            //ignore errors
            //undocumented return code, does not work on IE6
            return S_OK;
        }
    }
}

如何将System.Windows.Forms.WebBrowser添加到System.Windows.Controls.StackPanel?有什么东西的包装纸吗?

要在 WPF 中添加 Window Form controls,您首先需要 WindowsFormsHost。将 WindowsFormHost 添加到您的 StackPanel,然后将您的 webbrowser 添加到 WindowsFormHostXAML 示例如下:

1.

    <WindowsFormsHost>
        <wf:MaskedTextBox x:Name="mtbDate" Mask="00/00/0000"/>
    </WindowsFormsHost>

2.

   <wfh:WindowsFormsHost Grid.Row="1"  x:Name="wbFormHost" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" TabIndex="6">
        <wf:WebBrowser x:Name="webBrowser" x:FieldModifier="public" Dock="Fill"/>
    </wfh:WindowsFormsHost>

其中 wfhxmlns:wfh="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"

在@Siderite Zackwehdex 的帮助下

我不得不添加对 WindowsFormsIntegration 的引用。转到项目并展开 References -> Add Reference -> Assemblies -> Framework -> 勾选 WindowsFormsIntegration.

然后我不得不更改以下位。

public class WithoutCloseButton : Window
        {
            private const int GWL_STYLE = -16;
            private const int WS_SYSMENU = 0x80000;

            [DllImport("user32.dll", SetLastError = true)]
            private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
            [DllImport("user32.dll")]
            private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

//THIS IS NEW
            public void HideButtons()
            {
                var hwnd = new WindowInteropHelper(this).Handle;
                SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_SYSMENU);
            }
        }

然后在 OpenBrowser() 中,我不得不将 WebBrowser 包装在 WindowsFormsHost

 private void OpenBrowser(PaymentViewModel viewModel, Uri uri)
 {
    viewModel.BrowserWindow = new WithoutCloseButton();
    viewModel.BrowserWindow.Closed += BrowserWindow_Closed;
    var browser = new MyWebBrowser();
    var stackPanel = new StackPanel { Orientation = System.Windows.Controls.Orientation.Vertical };
    var formsHost = new WindowsFormsHost {Child = browser};
    stackPanel.Children.Add(formsHost);
    viewModel.BrowserWindow.Content = stackPanel;
//....    then            
 browser.Navigate("about:blank");
 browser.DocumentCompleted += delegate(object obj, WebBrowserDocumentCompletedEventArgs e)
{
    if (e.Url.ToString() == "about:blank")
    {
        ((MyWebBrowser)obj).Navigate(uri);
    }

    if (e.Url.ToString().ToLower().Contains("accepted"))
    {
        ViewModel.AuthCode = this.GetAuthToken();
        ViewModel.updateUiWhenDoneWithPayment_RunWorkerCompleted(new object(), null);
        ViewModel.BrowserWindow.Close();
        ViewModel.BrowserWindow = null;
    }
    //THIS IS NEW
    if (e.Url.ToString().ToLower().Contains("payment/confirmation"))
    {
        viewModel.BrowserWindow.HideButtons();
    }
};