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

时间:2016-04-18 10:22:03

标签: c# wpf winforms webbrowser-control uielement

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

当代理点击链接时,我需要打开webbrowser窗口,该窗口在某些页面上禁用(或隐藏)关闭(或隐藏)按钮而不在其他页面上。原因是他们被重定向到收取付款的第三方支付系统,如果他们在收取付款后关闭浏览器窗口但在重定向回我们的系统之前,我们没有收到第三方向客户收费时收到的付款通知。 / p>

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

  

错误无法转换   ' Desktop.ViewModels.PaymentViewModel.NavigateToTakePaymentCommand.MyWebBrowser'   到' 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?是否有像某个东西的包装?

2 个答案:

答案 0 :(得分:0)

要在Window中添加Form controls WPF,首先需要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"

答案 1 :(得分:0)

在@Siderite Zackwehdex的帮助下

我必须添加对WindowsFormsIntegration的引用。转到项目并展开References - &gt; Add Reference - &gt; Assemblies - &gt; Framework - &gt;勾选WindowsFormsIntegration

enter image description here

然后我不得不改变以下几点。

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();
    }
};