将 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
添加到 WindowsFormHost
。 XAML
示例如下:
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>
其中 wfh
是 xmlns: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();
}
};
我需要将 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
添加到 WindowsFormHost
。 XAML
示例如下:
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>
其中 wfh
是 xmlns: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();
}
};