Disable context menu webbrowser control - c#

I am using the WPF WebBrowser control to display a PDF. I want to disable the context menu.
I have already tried the following -
Disable context menu in Internet Explorer control -
In the constructor, added the following -
webBrowser.LoadCompleted +=new LoadCompletedEventHandler(webBrowser_LoadCompleted);
// Event Handler
public void webBrowser_LoadCompleted(object sender, NavigationEventArgs e )
{
webBrowser.ContextMenu = null;
var t = webBrowser.Document as System.Windows.Forms.HtmlDocument;
// t is always coming as null, even though I can clearly see the pdf in the web browser control.
if(t != null)
{
t.ContextMenuShowing += new System.Windows.Forms.HtmlElementEventHandler(t_ContextMenuShowing);
}
}
Also checked http://social.msdn.microsoft.com/forums/en-US/wpf/thread/7c283faf-16c8-4b4e-a362-f292e3032abb/.
Used the approach to set the registry - HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Internet Explorer\Restrictions\NoBrowserContextMenu to DWORD 1.
When I set the regisrty, the PDF does not get displayed properly.
Also, since I am using PDF to display, I cannot set - in body -
oncontextmenu="return false;"
Cannot set IsWebBrowserContextMenuEnabled as I am using WPF web browser control.

It could be because of the PDF visualizer that wants to show it's own context menu.
Which context menu are you seeing? The one of IE or the one of the PDF visualizer?
I would also try to use the System.Windows.Forms.WebBrowser (you can use it in WPF). I used it in a WPF application because it has more functionality than the one of WPF.

You can wrap the Windows Forms WebBrowser to be bindable and disable the context menu (and access to other properties) in an easy way:
public class WindowsFormsWebBrowser : WindowsFormsHost
{
public static readonly DependencyProperty HtmlProperty =
DependencyProperty.Register(
"Html",
typeof(string),
typeof(WindowsFormsWebBrowser),
new PropertyMetadata(string.Empty, OnHtmlChanged, null));
public static readonly DependencyProperty IsContentMenuEnabledProperty =
DependencyProperty.Register(
"IsContentMenuEnabled",
typeof(bool),
typeof(WindowsFormsWebBrowser),
new PropertyMetadata(true, OnIsContextMenuEnabledChanged));
private readonly System.Windows.Forms.WebBrowser webBrowser = new System.Windows.Forms.WebBrowser();
public WindowsFormsWebBrowser()
{
Child = webBrowser;
}
public string Html
{
get { return GetValue(HtmlProperty) as string; }
set { SetValue(HtmlProperty, value); }
}
public bool IsContentMenuEnabled
{
get { return (bool)GetValue(IsContentMenuEnabledProperty); }
set { SetValue(IsContentMenuEnabledProperty, value); }
}
private static void OnHtmlChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var browser = d as WindowsFormsWebBrowser;
if (browser == null)
{
return;
}
browser.webBrowser.DocumentText = (string)e.NewValue;
}
private static void OnIsContextMenuEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var browser = d as WindowsFormsWebBrowser;
if (browser == null)
{
return;
}
browser.webBrowser.IsWebBrowserContextMenuEnabled = (bool)e.NewValue;
}
}
Here the steps to reference Windows Forms controls in a WPF project.

Here is a solution:
private void WebBrowser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
((WebBrowser)sender).InvokeScript("eval",
"$(document).contextmenu(function() { return false; });");
}

Just use
// Disable the Context menu inside the web browser
webBrowser1.IsWebBrowserContextMenuEnabled = false;
i tried this in Windows Applications

Related

How to add UIContextMenuInteraction to button on Xamarin Forms?

I need to add a context menu to a button for Xamarin iOS.
I found an example on the apple developer site.
So I need to do quite a similar context menu but it should be anchored to the button element.
I created control and named it InteractionButton
public class InteractionButton : Button
{
public static readonly BindableProperty ButtonsListProperty = BindableProperty.Create(
nameof(ButtonsList), typeof(List<string>), typeof(InteractionButton));
public List<string> ItemsList
{
get => (List<string>) GetValue(ButtonsListProperty);
set => SetValue(ButtonsListProperty, value);
}
}
Also, I created a simple iOS renderer for the control -
[assembly: ExportRenderer(typeof(InteractionButton), typeof(InteractionButtonRenderer))]
public class InteractionButtonRenderer : ButtonRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (e.NewElement is InteractionButton button)
{
// create context menu from button.ItemsList
// NativeView.AddInteraction(new UIContextMenuInteraction());
}
}
}
The problem is that I don't know how should I build UIContextMenuInteraction. We should pass an instance of type IUIContextMenuInteractionDelegate into the UIContextMenuInteraction object.
I could not find any examples of how to do it. All that I have is an example from the apple developer site:
let button = UIButton(type: .system)
button.setImage(UIImage(systemName: "plus"), for: .normal)
let barButton = UIBarButtonItem(customView: button)
self.navigationItem.rightBarButtonItem = barButton
let interaction = UIContextMenuInteraction(delegate: self)
button.addInteraction(interaction)
extension ViewController: UIContextMenuInteractionDelegate {
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint)
-> UIContextMenuConfiguration? {
return UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { suggestedActions in
let importAction = UIAction(title: "Import", image: UIImage(systemName: "folder")) { action in }
let createAction = UIAction(title: "Create", image: UIImage(systemName: "square.and.pencil")) { action in }
return UIMenu(title: "", children: [importAction, createAction])
}
}
}
Is there a simple way of adding context menu interaction to my native control?
I test with the following code it works fine , just long click on the button it will shows the menu .
InteractionButton
public class InteractionButton : Button
{
public static readonly BindableProperty ItemsListProperty = BindableProperty.Create(
nameof(ItemsList),
typeof(List<string>),
typeof(InteractionButton));
public List<string> ItemsList
{
get => (List<string>)GetValue(ItemsListProperty);
set => SetValue(ItemsListProperty, value);
}
}
Xaml
<local:InteractionButton HeightRequest="100" WidthRequest="100" Text="Click on me" ItemsList="{Binding list}"/>
Custom renderer
[assembly: ExportRenderer(typeof(InteractionButton), typeof(MyRenderer))]
namespace FormsApp.iOS
{
class MyRenderer : ButtonRenderer , IUIContextMenuInteractionDelegate
{
public UIContextMenuConfiguration GetConfigurationForMenu(UIContextMenuInteraction interaction, CGPoint location)
{
List<UIMenuElement> elementList = new List<UIMenuElement>();
foreach (var item in (Element as InteractionButton).ItemsList) {
UIAction action = UIAction.Create(item, UIImage.FromFile("dog.png"), item, (a) => {
Console.WriteLine("Click on action1");
});
elementList.Add(action);
}
UIMenu menu = UIMenu.Create("Menu", elementList.ToArray());
return UIContextMenuConfiguration.Create(null,null,(suggestedActions) => menu);
}
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (Control != null)
{
var interaction = new UIContextMenuInteraction(this);
Control.AddInteraction(interaction);
}
}
}
}

Attached Property for Binding to WebBrowser not working

I have been looking for a way to get the HTML out of a WPF WebBrowser control. The two best options I have found are to bind a customer attached property to the property in the application or to build a new control from the WebBrowser control. Considering my level of knowledge and the fact that (as of now I really only need this one time) I chose the first. I even considered breaking MVVM style and using code-behind but I decided not to give up in the binding.
I found several examples on creating the attached property, I finally chose this one, from here Here:
namespace CumminsInvoiceTool.HelperClasses
{
public static class WebBrowserExtentions
{
public static readonly DependencyProperty DocumentProperty =
DependencyProperty.RegisterAttached("Document", typeof(string), typeof(WebBrowserExtentions), new UIPropertyMetadata(null, DocumentPropertyChanged));
public static string GetDocument(DependencyObject element)
{
return (string)element.GetValue(DocumentProperty);
}
public static void SetDocument(DependencyObject element, string value)
{
element.SetValue(DocumentProperty, value);
}
public static void DocumentPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
WebBrowser browser = target as WebBrowser;
if (browser != null)
{
string document = e.NewValue as string;
browser.NavigateToString(document);
}
}
}
}
I also added the following to the xaml for the WebBrowser control (I have tried both with and without the "Path=" in the xaml:
<WebBrowser local:WebBrowserExtentions.Document="{Binding Path=PageCode}" Source="https://www.cummins-distributors.com/"/>
My View has a tab control one tab has the WebBrowser control and another tab has a textbox. When I click the get code the viewModel runs a function to set property bound to the textbox to the string the attached property of the WebBrowser is bound to. Below is the code of my ViewModel.
namespace CumminsInvoiceTool.ViewModels
{
class ShellViewModel : Screen
{
private string _browserContent;
public string BrowserContent
{
get { return _browserContent; }
set {
_browserContent = value;
NotifyOfPropertyChange(() => BrowserContent);
}
}
private string _pageCode;
public string PageCode
{
get { return _pageCode; }
set {
_pageCode = value;
NotifyOfPropertyChange(() => PageCode);
}
}
public void StartProgressCommand()
{
}
public void GetContent()
{
if (!string.IsNullOrEmpty(PageCode))
{
BrowserContent = PageCode;
}
else
{
MessageBox.Show("There is no cintent to show", "No content Error", MessageBoxButton.OK);
}
}
}
}
The application compiles and runs but when I click "Get Code" I am getting the messagebox for "PageCode" is empty.
When I set a break point at the beginning of the function for the button, the PageCode string is showing "null".
Is this an issue because I am using Caliburn.Micro or am I missing something else?
------- EDIT for comments ----------
The button calls GetContent() in the "ShellViewModel" code above. I know the button is bound and working because the app is showing the custom messagebox I have set up to let me know when "pageCode" is null or empty.
The textbox looks like:
<TextBox x:Name="BrowserContent"/>

WinRT WebView NavigateToString bug

I have a strange problem with the WebView component in WinRT. I use it to display either a Website via Soure property binding or local content with NavigateToString.
My problem is the following:
If I change the Source property, it naviagtes to the Website. Then, I call NavigateToString and it displays the content correctly. After that I change the Source property again, but navigation doesn't start and the local content remains present.
Also if I first call NavigateToString and then change Source property, no navigation starts.
I prepared a small sample project to illustrate my problem: http://1drv.ms/1HI8p3I
EDIT:
I updated the sample project above. I tried to call Naviagte via an Attached Property instead of changing the Source property but I got the same issue. Once I call NavigateToString, all other updates of bindings don't work.
This is my class with the Attached properties for WebView:
public class WebViewEx
{
#region ContentString
public static readonly DependencyProperty ContentStringProperty =
DependencyProperty.RegisterAttached("ContentString", typeof(string), typeof(WebViewEx), new PropertyMetadata("", new PropertyChangedCallback(OnContentStringPropertyChanged)));
public static void SetContentString(DependencyObject obj, string contentString)
{
obj.SetValue(ContentStringProperty, contentString);
}
public static string GetContentString(DependencyObject obj)
{
return (string)obj.GetValue(ContentStringProperty);
}
private static void OnContentStringPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
WebView webView = d as WebView;
if (webView != null)
{
webView.NavigateToString((string)e.NewValue);
}
}
#endregion
#region UriString
public static readonly DependencyProperty UriStringProperty =
DependencyProperty.RegisterAttached("UriString", typeof(string), typeof(WebViewEx), new PropertyMetadata("", new PropertyChangedCallback(OnUriStringPropertyChanged)));
public static void SetUriString(DependencyObject obj, string uriString)
{
obj.SetValue(UriStringProperty, uriString);
}
public static string GetUriString(DependencyObject obj)
{
return (string)obj.GetValue(UriStringProperty);
}
private static void OnUriStringPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
WebView webView = d as WebView;
if (webView != null)
{
webView.Navigate(new Uri((string)e.NewValue));
}
}
#endregion
}

Hide the ToggleButton on WPF Expander via Binding

I am trying to dynamically hide the Toggle Button on an Expander using a Property on my ViewModel set to the Visibility property. At least that is my thought. Is there a way to just alter that one setting on the ToggleButton control without having to do the ENTIRE template of the Toggle Button in my xaml?
You could use the Loaded event for the Expander and set up the Binding in the event handler or if you want a reusable way without code behind you could use an attached behavior.
The attached behavior finds the ToggleButton inside the Template and sets up the Binding to the attached property ToggleButtonVisibility.
Uploaded a sample app here: ExpanderToggleButtonVisibilityTest.zip
Use it like this
<Expander Name="expander"
behaviors:ExpanderBehavior.BindToggleButtonVisibility="True"
behaviors:ExpanderBehavior.ToggleButtonVisibility="{Binding YourVisibilityProperty}"
.../>
ExpanderBehavior
public class ExpanderBehavior
{
public static DependencyProperty BindToggleButtonVisibilityProperty =
DependencyProperty.RegisterAttached("BindToggleButtonVisibility",
typeof(bool),
typeof(ExpanderBehavior),
new PropertyMetadata(false, OnBindToggleButtonVisibilityChanged));
public static bool GetBindToggleButtonVisibility(Expander expander)
{
return (bool)expander.GetValue(BindToggleButtonVisibilityProperty);
}
public static void SetBindToggleButtonVisibility(Expander expander, bool value)
{
expander.SetValue(BindToggleButtonVisibilityProperty, value);
}
private static void OnBindToggleButtonVisibilityChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
Expander expander = target as Expander;
if (expander.IsLoaded == true)
{
BindToggleButtonVisibility(expander);
}
else
{
RoutedEventHandler loadedEventHandler = null;
loadedEventHandler = new RoutedEventHandler(delegate
{
BindToggleButtonVisibility(expander);
expander.Loaded -= loadedEventHandler;
});
expander.Loaded += loadedEventHandler;
}
}
private static void BindToggleButtonVisibility(Expander expander)
{
ToggleButton headerSite = expander.Template.FindName("HeaderSite", expander) as ToggleButton;
if (headerSite != null)
{
Binding visibilityBinding = new Binding
{
Source = expander,
Path = new PropertyPath(ToggleButtonVisibilityProperty)
};
headerSite.SetBinding(ToggleButton.VisibilityProperty, visibilityBinding);
}
}
#region ToggleButtonVisibilityProperty
public static DependencyProperty ToggleButtonVisibilityProperty =
DependencyProperty.RegisterAttached("ToggleButtonVisibility",
typeof(Visibility),
typeof(ExpanderBehavior),
new PropertyMetadata(Visibility.Visible));
public static Visibility GetToggleButtonVisibility(Expander expander)
{
return (Visibility)expander.GetValue(ToggleButtonVisibilityProperty);
}
public static void SetToggleButtonVisibility(Expander expander, Visibility value)
{
expander.SetValue(ToggleButtonVisibilityProperty, value);
}
#endregion // ToggleButtonVisibilityProperty
}

Change AttachedProperty of WebBrowser when navigating

I used a those article to create AttachedProperty of Webbrowser control, so I can bind the “BindableSource” to my public property “Path”. It is great and work well with one small disadvantage.
In my ViewModel constructor the property is set to:
Path = new Uri("http://microsoft.com");
When the page is loaded I navigate to another link and “WebBrowser.Source” property is changed but “WebBrowser.BindableSource” is not changed.
When I click a button which set again:
Path = new Uri("http://microsoft.com");
The “BindableSourcePropertyChanged” is not called because the property has those value.
I had an idea how to solve it but its not good, because slow the performance, It is to set Path to another URL and after that set it to real URL (http://microsoft.com).
Path = new Uri("http://google.com");
Path = new Uri("http://microsoft.com");
Can you give me please a better idea, how can I solved it.
Thanks in advanced.
I propose to synchronize BindableSource with Navigated event.
You coukld achieve this by exposing another one attached behaviour at your WebBrowserUtility class, that reacts on Navigated event like this:
public static readonly DependencyProperty ShouldHandleNavigatedProperty =
DependencyProperty.RegisterAttached(
"ShouldHandleNavigated",
typeof(Boolean),
typeof(WebBrowserUtility),
new UIPropertyMetadata(false, ShouldHandleNavigatedPropertyChanged));
public static Boolean GetShouldHandleNavigated(DependencyObject obj)
{
return (Boolean)obj.GetValue(BindableSourceProperty);
}
public static void SetShouldHandleNavigated(DependencyObject obj, Boolean value)
{
obj.SetValue(ShouldHandleNavigatedProperty, value);
}
public static void ShouldHandleNavigatedPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
WebBrowser browser = o as WebBrowser;
if (browser != null)
{
if ((bool)e.NewValue)
{
browser.Navigated += new NavigatedEventHandler(Browser_Navigated);
}
else
{
browser.Navigated -= new NavigatedEventHandler(Browser_Navigated);
}
}
}
private static void Browser_Navigated(object sender, NavigationEventArgs e)
{
WebBrowser browser = sender as WebBrowser;
if (browser != null)
{
browser.SetValue(WebBrowserUtility.BindableSourceProperty, browser.Source.AbsoluteUri);
}
}
Usage in xaml:
<WebBrowser self:WebBrowserUtility.BindableSource="{Binding WebAddress}"
self:WebBrowserUtility.ShouldHandleNavigated="True"/>
P.S. I should admit that this implementation is rather dirty, because setting of BindableSource inside Navigated event handler forces one additional event fireing. But this code works, and you could consider about its improvement.
EDITED
public static class WebBrowserUtility
{
...
private const string _SkipSourceChange = "Skip";
public static void BindableSourcePropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
WebBrowser browser = o as WebBrowser;
if (browser != null)
{
string uri = e.NewValue as string;
if (!_SkipSourceChange.Equals(browser.Tag))
{
browser.Source = uri != null ? new Uri(uri) : null;
}
}
}
private static void Browser_Navigated(object sender, NavigationEventArgs e)
{
WebBrowser browser = sender as WebBrowser;
if (browser != null)
{
if (WebBrowserUtility.GetBindableSource(browser) != e.Uri.ToString())
{
browser.Tag = _SkipSourceChange;
browser.SetValue(WebBrowserUtility.BindableSourceProperty, browser.Source.AbsoluteUri);
browser.Tag = null;
}
}
}
}

Categories

Resources