Link click overriding in a webBrowser control - c#

I am using Virtual Studio Community in C# (.Net 4.5).
I have a simple form, which contains one button and one webBrowser control.
When I click the button, I make the webBrowser navigate to google.com.
Then, when the page is loaded, I try to override the linkClick events as I saw in a solution I read on this site (stackoverflow) earlier.
But then, when I click on a link on the loaded page, it says the navigation was cancelled, but it navigates anyways.
What am I doing wrong?
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
webBrowser1.Navigate("http://www.google.com/");
}
private bool bCancel = false;
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
for (int i = 0; i < webBrowser1.Document.Links.Count; i++)
{
webBrowser1.Document.Links[i].Click += new HtmlElementEventHandler(this.LinkClick);
}
}
private void LinkClick(object sender, System.EventArgs e)
{
bCancel = true;
MessageBox.Show("Link Was Clicked Navigation was Cancelled");
}
private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
if (bCancel == true)
{
e.Cancel = true;
bCancel = false;
}
}
}

You need to bind the WebBrowserControl.Navigating event to the handler you've written; having the handler's name matching the control underscore event name isn't enough.
So you can do this in the Form1's constructor:
public Form1()
{
InitializeComponent();
webBrowser1.Navigating += new WebBrowserNavigatingEventHandler(webBrowser1_Navigating);
}
Better yet, add a Load event and do the same there. Check out the official documentation on the subject.

Related

How to stop a panel loading each time i press it's button

I have one Windows Form application and there are several user controls in it.
I show them by pressing their buttons via this method;
private void UC_Bring(Control uc)
{
uc.Dock = DockStyle.Fill;
panelControls.Controls.Clear();
panelControls.Controls.Add(uc);
}
For example;
-First button is "Home" button. (this is the startup page)
-Second button is "Operation" button.
I click the "Operation" button and i fill some text boxes in this user control. But if i click the "Operation" button again, the user control resets itself and text boxes are being clear.
I want not to bring the user control again if mentioned user control is in use / already brought to screen. How can i do that?
Screenshot
Thanks in advance.
I tried that before
private void UC_Bring(Control uc)
{
uc.Dock = DockStyle.Fill;
if (uc.Visible!=true)
{
panelControls.Controls.Clear();
panelControls.Controls.Add(uc);
}
}
I edit this with button click event together with bringing method;
private void UC_getir(Control uc) //User control çağırma metodu
{
uc.Dock = DockStyle.Fill;
panelControls.Controls.Clear();
panelControls.Controls.Add(uc);
}
private void BtnOp_Click(object sender, EventArgs e)
{
UC_Op ucOp = new UC_Op();
UC_getir(ucOp);
}
You are very likely creating a new control every single time. You just need to Clear() the Panel and Add() the new UserControl each different clicks. If the UserControl is not in a container it is not visible. That mean you also don't need to fool around with the visibility. Here's a totally working solution of just that behavior.
public partial class Form1 : Form
{
private ucHome HomeUserControl = new ucHome();
private ucOperations OperationsUserControl = new ucOperations();
private ucMaterials MaterialsUserControl = new ucMaterials();
private ucSettings SettingsUserControl = new ucSettings();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
HomeUserControl.Dock = DockStyle.Fill;
OperationsUserControl.Dock = DockStyle.Fill;
MaterialsUserControl.Dock = DockStyle.Fill;
SettingsUserControl.Dock = DockStyle.Fill;
}
private void UC_Bring(Control uc)
{
panelControls.Controls.Clear();
panelControls.Controls.Add(uc);
}
private void btnHome_Click(object sender, EventArgs e)
{
UC_Bring(HomeUserControl);
}
private void btnOperations_Click(object sender, EventArgs e)
{
UC_Bring(OperationsUserControl);
}
private void btnMaterials_Click(object sender, EventArgs e)
{
UC_Bring(MaterialsUserControl);
}
private void btnSettings_Click(object sender, EventArgs e)
{
UC_Bring(SettingsUserControl);
}
}
public class ucHome : UserControl { }
public class ucOperations : UserControl { }
public class ucMaterials : UserControl { }
public class ucSettings : UserControl { }

Wait for Input in User Control

I'm trying to implement a customized exit prompt in my WinForms. (I should not be using DialogBox)
I have a User Control Object placed in my main form that is invisible and disabled by default. Clicking in a certain button I have placed on the form shows and enables the object, disabling everything in my form except the User Control.
private void btn_close_Click(object sender, EventArgs e) {
prompt1.Visible = true;
prompt1.Enabled = true;
disableControls();
//Wait for a button to be pressed in prompt1
//Make an action based on a button pressed.
//closeApp returns a boolean
if (!prompt1.closeApp)
{
prompt1.Visible = false;
prompt1.Enabled = false;
enableControls();
}
else
{
Application.Exit();
}
}
Here's my code at the prompt object:
public partial class Prompt : UserControl
{
bool exit;
public bool closeApp
{
get{return exit;}
}
public Prompt()
{
InitializeComponent();
}
private void btn_yes_Click(object sender, EventArgs e)
{
exit = true;
}
private void btn_no_Click(object sender, EventArgs e)
{
exit = false;
this.Hide();
}
}
What I want to do is wait for a button to be pressed in my prompt object before proceeding to the next line in the btn_close_Click().
What should I do? Is there a better way to implement this?
Add events to your usercontrol then handle those events on your main form.
In your usercontrol:
public event EventHandler<EventArgs> ExitCancelled;
public event EventHandler<EventArgs> ExitApplication;
private void btn_yes_Click(object sender, EventArgs e)
{
ExitApplication?.Invoke(this, EventArgs.Empty);
}
private void btn_no_Click(object sender, EventArgs e)
{
ExitCancelled?.Invoke(this, EventArgs.Empty);
}
Handle the events on your form:
public void prompt1_ExitApplication(object sender, EventArgs e)
{
Application.Exit();
}
public void prompt1_ExitCancelled(object sender, EventArgs e)
{
prompt1.Hide();
enablecontrols();
}

how to add dynamically and remove a user control from a user control in a form

I am struggling in adding a dynamic and removing a user control into the form. I have a form and inside my form I have a panel which it has a static control.
What I am trying to achieved is to add the user control into the panel. Though it was easy to add but I know there is a better way out there to do this.
Adding a user control to my panel by clicking a button in the form.
private void btnadd_Click(object sender, EventArgs e)
{
UserControl1 usr = new UserControl1
pnlUI.SuspendLayout();
pnlUI.Controls.Clear();
pnlUI.Controls.Add(usr);
pnlUI.ResumeLayout(false);
}
// This one adds it and clearing the control that was already in the panel of the form.
Now, I get stacked here in removing the user control that was added and trying to display again the control that was in the panel that was been removed or cleared.
On my user control there is a back button on that back button I am trying to dispose the user control. But after that the original control is no longer there and the panel is empty already.
Any suggestions?
You could add an instance variable to your form to keep track of the previous control. This assumes that there will only ever be one control in the panel.
In your class:
private Control _previousPanelContent;
then in your method:
private void btnadd_Click(object sender, EventArgs e)
{
UserControl1 usr = new UserControl1();
pnlUI.SuspendLayout();
// check if there's already content in the panel, if so, keep a reference.
if (pnlUI.Controls.Count > 0)
{
_previousPanelContent = pnlUI.Controls[0];
pnlUI.Controls.Clear();
}
pnlUI.Controls.Add(usr);
pnlUI.ResumeLayout(false);
}
then later when you want to go back:
pnlUI.SuspendLayout();
pnlUI.Controls.Clear();
// if the previous content was set, add it back to the panel
if (_previousPanelContent != null)
{
pnlUI.Controls.Add(_previousPanelContent);
}
pnlUI.ResumeLayout(false);
Here's a simple example of the Event approach mentioned in the Comments above.
The UserControl with a "Back" event:
public partial class UserControl1 : UserControl
{
public event dlgBack Back;
private UserControl1 _previous = null;
public delegate void dlgBack(UserControl1 sender, UserControl1 previous);
public UserControl1(UserControl1 previous)
{
InitializeComponent();
this._previous = previous;
}
private void btnBack_Click(object sender, EventArgs e)
{
if (Back != null)
{
Back(this, _previous);
}
}
}
The Form then creates the UserControl and subscribes to the Event:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnAdd_Click(object sender, EventArgs e)
{
UserControl1 prevUsr = pnlUI.Controls.OfType<UserControl1>().FirstOrDefault();
UserControl1 usr = new UserControl1(prevUsr);
usr.Back += usr_Back;
pnlUI.Controls.Clear();
pnlUI.Controls.Add(usr);
}
void usr_Back(UserControl1 sender, UserControl1 previous)
{
pnlUI.Controls.Remove(sender);
if (previous != null)
{
pnlUI.Controls.Add(previous);
}
}
}
You are declaring your user control inside your button callback function (callback function is a function called at runtime when an event occurs, such as a button click etc.).
This means that the variable holding your user control is inaccessible outside it, and therefore you are not able to use it from another callback function.
Instead of doing this:
private void btnadd_Click(object sender, EventArgs e)
{
//This is not accessible outside the callback function.
UserControl1 usr = new UserControl1();
pnlUI.SuspendLayout();
pnlUI.Controls.Clear();
pnlUI.Controls.Add(usr);
pnlUI.ResumeLayout(false);
}
Try declaring a property that will hold the user control, in order to use it elsewhere:
//Declare a private property - you can adjust the access level of course,
//depending on what you need.
//You can even declare a field variable for the same cause,such as
//private UserControl _myUserControl;
//This declaration is in the class body.
private UserControl MyUserControl { get; set; }
//Your addition callback function.
private void btnadd_Click(object sender, EventArgs e)
{
//The user control is now assigned to the property.
MyUserControl = new UserControl1();
pnlUI.SuspendLayout();
pnlUI.Controls.Clear();
pnlUI.Controls.Add(MyUserControl);
pnlUI.ResumeLayout(false);
}
//Your removal callback function.
private void btnremove_Click(object sender, EventArgs e)
{
//...
//Use the property value here.
pnlUI.Controls.Remove(MyUserControl);
//...
}
I collected the solutions above (mostly the first of #Idle_Mind) I just added and adjusted some lines ; I will use his sentences:
Here's a simple example of the Event approach mentioned in the Comments above.
The UserControl with a "Back" event:
No Change here
public partial class UserControl1 : UserControl
{
public event dlgBack Back;
private UserControl1 _previous = null;
public delegate void dlgBack(UserControl1 sender, UserControl1 previous);
public UserControl1(UserControl1 previous)
{
InitializeComponent();
this._previous = previous;
}
private void btnBack_Click(object sender, EventArgs e)
{
if (Back != null)
{
Back(this, _previous);
}
}
}
The Form then creates the UserControl and subscribes to the Event:
Let take a look at commented lines
public partial class Form1 : Form
{
//prevUsr is global instead
private UserControl1 prevUsr = null;
public Form1()
{
InitializeComponent();
}
private void btnAdd_Click(object sender, EventArgs e)
{
//prevUsr is removed from here
//UserControl1 prevUsr = pnlUI.Controls.OfType<UserControl1>().FirstOrDefault();
UserControl1 usr = new UserControl1(prevUsr);
usr.Back += usr_Back;
pnlUI.Controls.Clear();
pnlUI.Controls.Add(usr);
//prevUsr is updated
prevUsr = usr;
}
void usr_Back(UserControl1 sender, UserControl1 previous)
{
pnlUI.Controls.Remove(sender);
//prevUsr is updated
prevUsr = previous;
if (previous != null)
{
pnlUI.Controls.Add(previous);
}
}
}
And, don't forget to set btnBack_Click for click of the UserControl's back button.
I hope this is helpful, it worked perfectly at my side ; I can send or share the full VS project (VS2012).
I hope it works for you,
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private int count = 0;
private LinkedList<UserControl1> lstControls = new LinkedList<UserControl1>();
private void btnAdd_Click(object sender, EventArgs e)
{
var c = new UserControl1();
if (pnlUI.Controls.Count > 0)
{
lstControls.AddLast(pnlUI.Controls[0] as UserControl1);
pnlUI.Controls.Clear();
}
c.lblTitle.Text = "Control #" + (++count).ToString();
pnlUI.Controls.Add(c);
}
private void btnBack_Click(object sender, EventArgs e)
{
if (lstControls.Last != null)
{
var lastControl = lstControls.Last.Value;
pnlUI.Controls.Clear();
pnlUI.Controls.Add(lastControl);
lstControls.RemoveLast();
}
}
}
I combine the answers of idle_mind,rdavisau and fabrice. I used rdavisau code in getting back the controls and idle_mind for the back event in the usercontrol and fabrice for his some modifications in the form.. I wish i can split the bounty into three,so I give it to idle mind..thanks all
I created a class:
class GetControls
{
private Control[] cntrl;
public Control[] Previous
{
get
{
return cntrl;
}
set
{
cntrl = value;
}
}
}
on my main form here is the revised code.
GetControls help = new GetControls();
private void btnpay_Click(object sender, EventArgs e)
{
TenderUI usr = new TenderUI(prevUsr);
usr.Back += usr_Back;
help.Previous = pnlUI.Controls.OfType<Control>().ToArray();
pnlUI.Controls.Clear();
pnlUI.Controls.Add(usr);
}
and to retrieve the controls
void usr_Back(TenderUI sender, TenderUI previous)
{
pnlUI.Controls.Remove(sender);
if (help.Previous != null)
{
foreach (Control ctr in help.Previous)
{
pnlUI.Controls.Add(ctr);
}
}
}

Handling Button Clicks from a different Class

I have a Form with Button ButtonGo.
and I have a class which takes a button through its constructor, then handles its events:
public class HandlingClass
{//.......
Button go ;
public HandlingClass(Button btn)
{
this.go = btn;
this.go.Click += new EventHandler(this.go_Click);
}
//.....
public void go_Click(object sender, EventArgs e)
{
//logic here
}
What am I doing wrong, and why isn't the event being raised when I press the Button in the caller form?
This code works for me
public class HandlingClass
{
Button go;
public HandlingClass(Button btn)
{
go = btn;
go.Click += go_Click;
}
void go_Click(object sender, RoutedEventArgs e)
{
throw new NotImplementedException();
}
}
and in your loaded event of the class having the button you just add the below code
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
HandlingClass hc=new HandlingClass(**MyButton**);
}
MyButton should be the reference to your button.

ShowDialog with Parent still enabled

In one of our apps we want to want to limit the user from opening other menu items when an existing menu item is already open. We are currently doing this:
private void menuItem1_Click(object sender, EventArgs e)
{
Myform f = new MyForm();
f.ShowDialog(this);
}
However in doing this, we lose the ability to interact at all with the parent window because internally, the parent.enabled property was set to false. Using the code above, if the user has menu item open and wants to move the parent window to see something on their desktop, they first must close the menu item, move the parent, and reopen the menu item.
I have come up with the follow method of doing the UI in a backgroundworker
public class BaseForm : Form
{
private bool _HasChildOpen;
protected BackgroundWorker bgThead;
public BaseForm()
{
_HasChildOpen = false;
bgThead = new BackgroundWorker();
bgThead.DoWork += new DoWorkEventHandler(OpenChildWindow);
bgThead.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.ClearChildWindows);
}
protected void ClearChildWindows(object sender, RunWorkerCompletedEventArgs e)
{
_HasChildOpen = false;
}
public void OpenChildWindow(object sender, DoWorkEventArgs e)
{
if (!_HasChildOpen)
{
Form f = (Form)e.Argument;
f.StartPosition = FormStartPosition.CenterScreen;
f.ShowDialog();
}
}
}
and then each menu item has the following code
private void menuItem1_Click(object sender, EventArgs e)
{
if (!bgThead.IsBusy)
{
bgThead.RunWorkerAsync(new Myform());
}
}
but this approach is a big no no. However, using invoke seems to get me back where I started:
private void doUIWork(MethodInvoker d)
{
if (this.InvokeRequired)
{
this.Invoke(d);
}
else
{
d();
}
}
public void OpenChildWindow(object sender, DoWorkEventArgs e)
{
if (!_HasChildOpen)
{
doUIWork(delegate() {
Form f = (Form)e.Argument;
f.StartPosition = FormStartPosition.CenterScreen;
f.ShowDialog();
});
//Form f = (Form)e.Argument;
//f.StartPosition = FormStartPosition.CenterScreen;
//f.ShowDialog();
}
}
How do I properly limit the user to just one menu item open, but at the same time leave the parent enabled such that it can be moved resized etc?
You will need to programmatically disable menu strip behavior once one of the forms is open. So if you have Form1 and Form2, (with a menuStrip on Form1 and toolStripMenuItem1, toolStripMenuItem2 on the menuStrip):
private void menuItem1_Click(object sender, EventArgs e)
{
var f2 = new Form2();
f2.FormClosing += f2_FormClosing;
f2.Show();
this.menuStrip1.Enabled = false;
}
private void menuItem2_Click(object sender, EventArgs e)
{
var f2 = new Form2();
f2.FormClosing += f2_FormClosing;
f2.Show();
this.menuStrip1.Enabled = false;
}
void f2_FormClosing(object sender, FormClosingEventArgs e)
{
this.menuStrip1.Enabled = true;
}
using the Show() method instead of ShowDialog() enables interaction with the parent control, though you will need to manually disable/enable behavior depending on when the child control is shown or not.

Categories