I am creating a winforms application which uses Gmaps.net. I am unable to alter the order in which on Load methods are being called. For some reason the map_load is being called before the man_Load. Is there any way to change the order of this ?
If I can provide any more information to help just ask.
Thanks!
Dan.
public partial class main : Form
{
public main()
{
InitializeComponent();
}
private void main_Load(object sender, EventArgs e)
{
MessageBox.Show("main_load");
}
private void map_Load(object sender, EventArgs e)
{
MessageBox.Show("map_load");
}
}
It seems that you used the WinForms designer to create the map. The code behind is in the InitializeComponent() method and seems that the map is being loaded before the MainForm is loaded.
My recommendation is to create the map, once the MainForm has been loaded:
public partial class main : Form
{
public main()
{
InitializeComponent();
}
private void main_Load(object sender, EventArgs e)
{
Control map = CreateMap();
map.Docking = DockStyle.Fill;
this.Controls.Add(map);
}
private Control CreateMap()
{
// Create a new GMaps.NET object, intialize it and return
}
}
Hope it helps.
Related
I've created a new form, in which I have a toolbox. When I press a button in that form, it should relay that information that has been entered by the user(toolboxbox value) to the main form, in which it should say that piece of information in a label.
Since the method to create that username from the toolbox is private, I cannot access it from any other way. Making it public does not seem to make a difference, neither does get,set (from the way I've been trying to atleast).
Picture that may help explaining it:
Code (in which to create user):
namespace WindowsFormsApplication3
{
public partial class Newuserform : Form
{
public Newuserform()
{
InitializeComponent();
}
private void buttonCreateUser_Click(object sender, EventArgs e)
{
string uname = textboxUsername.ToString();
}
public void Unamecreate()
{
}
}
}
Form1 Code (To receive created user):
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
{
Aboutform form2 = new Aboutform();
form2.Show();
}
private void newLocalUserToolStripMenuItem_Click(object sender, EventArgs e)
{
Newuserform formnewuser = new Newuserform();
formnewuser.Show();
}
}
}
you have a lot of options.
One way is to create an event and handle it in the main form.
public partial class Newuserform : Form
{
//the public property
public event EventHandler<string> UnameChanged;
public Newuserform()
{
InitializeComponent();
}
private void buttonCreateUser_Click(object sender, EventArgs e)
{
if (UnameChanged != null)
UnameChanged(textboxUsername.ToString()); //fire the event
}
}
Now, to "handle" the event, do the following in your main form:
private void newLocalUserToolStripMenuItem_Click(object sender, EventArgs e)
{
Newuserform formnewuser = new Newuserform();
formnewuser.UnameChanged += Handler;
formnewuser.Show();
}
private void Handler (object sender, string Uname)
{
// do something wit the new Uname.
}
note: recreating the Newuserform will require to cleanup previous attached resources.
I am working with windowsFrom in c#. I am trying to call mainfrom method in one of the from in user control.
I have mainfrom like this
namespace Project
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
public void TempCommand()
{
StartTemp();
}
}
}
I have the button click in the user control. When i click that button then it will open another form. I have the code like this in the user control.
private TempCalib _tempCalib = new TempCalib();
private void calibBtn_Click(object sender, EventArgs e)
{
_tempCalib.Show();
}
it will open another from and i have one button in that from. I need to call mainfrom method when i click "Ok" button in this from.
namespace Project
{
public partial class TempCalib : Form
{
public TempCalib()
{
InitializeComponent();
}
private void OkButton_Click(object sender, EventArgs e)
{
// I need to call the mainfrom "TempCommand" method here.
this.Hide();
}
}
}
Can anyone help me how to do this.
Thanks.
Quick answer
Just add a reference to the primary form in your secondary form:
public partial class TempCalib : Form
{
private MainForm _main
public TempCalib(MainForm main) : this()
{
_main = main;
}
/// Other stuffs
}
Then assign value when you construct your secondary form:
private TempCalib _tempCalib;
private void calibBtn_Click(object sender, EventArgs e)
{
if (_tempCalib == null)
_tempCalib = new TempCalib(this);
_tempCalib.Show();
}
If calibBtn_Click isn't inside MainForm (but it's inside a UserControl on it) then you can replace _tempCalib initialization with:
_tempCalib = new TempCalib((MainWindow)FindForm());
You'll be then able to call the primary form:
private void OkButton_Click(object sender, EventArgs e)
{
_main.TempCommand();
this.Hide();
}
Notes: this is just one option, you may create a property to hold MainForm reference (so secondary form can be reused and it'll be more designer friendly) moreover TempCalib is not an UserControl but a Form (pretty raw but for an UserControl you may just check its parent Form and cast it to proper type).
Improvements
Such kind of references are often an alert. Usually UI components shouldn't not be so coupled and a public Form's method to perform something very often is the signal that you have too much logic in your Form. How to improve this?
1. DECOUPLE CONTROLS. Well a first step may be to decouple them a little bit, just add an event in TempCalib and make MainForm its receiver:
public partial class TempCalib : Form
{
public event EventHandler SomethingMustBeDone;
private void OkButton_Click(object sender, EventArgs e)
{
OnSomethingMustBeDone(EventArgs.Empty); / TO DO
this.Hide();
}
}
Then in MainForm:
private TempCalib _tempCalib;
private void calibBtn_Click(object sender, EventArgs e)
{
if (_tempCalib == null)
{
_tempCalib = new TempCalib();
_tempCalib.SomethingMustBeDone += _tempCalib_SomethingMustBeDone;
// In _tempCalib_SomethingMustBeDone you'll invoke proper member
// and possibly hide _tempCalib (remove it from OkButton_Click)
}
_tempCalib.Show();
}
2. DECOUPLE LOGIC FROM CONTROLS. UI changes pretty often, logic not (and when it changes probably isn't in parallel with UI). This is just the first step (now TempCalib isn't aware of who will use it). Next step (to be performed when too much things happen inside your form) is to remove this kind of logic from the form itself. Little example (very raw), keep TempCalib as before (with the event) and change MainForm to be passive:
public partial class MainForm : Form
{
public event EventHandler Calibrate;
protected virtual void OnCalibrate(EventArgs e)
{
// TODO
}
}
Now let's create a class to control the flow and logic:
public class MyTaskController
{
private MainForm _main;
private TempCalib _tempCalib;
public void Start()
{
_main = new MainForm();
_main.Calibrate += OnCalibrationRequested;
_main.Show(); // Or whatever else
}
private void OnCalibrationRequested(object sender, EventArgs e)
{
if (_tempCalib == null)
{
_tempCalib = new TempCalib();
_tempCalib.SomethingMustBeDone += OnSomethingMustBeDone();
}
_tempCalib.Show();
}
private OnSomethingMustBeDone(object sender, EventArgs e)
{
// Perform the task here then hide calibration window
_tempCalib.Hide();
}
}
Yes, you'll need to write much more code but this will decouple logic (what to do as response to an action, for example) from UI itself. When program grows up this will help you to change UI as needed keeping logic unaware of that (and in one well defined place). I don't even mention that this will allow you to use different resources (people) to write logic and UI (or to reuse logic for different UI, WinForms and WPF, for example). Anyway IMO the most obvious and well repaid benefit is...readability: you'll always know where logic is and where UI management is, no search, no confusion, no mistakes.
3. DECOUPLE LOGIC FROM IMPLEMENTATION. Again you have more steps to perform (when needed). Your controller is still aware of concrete types (MainForm and TempCalib). In case you need to select a different form at run-time (for example to have a complex interface and a simplified one or to use dependency injection) then you have to decouple controller using interfaces. Just an example:
public interface IUiWindow
{
void Show();
void Hide();
}
public interface IMainWindow : IUiWindow
{
event EventHandler Calibrate;
}
public interface ICalibrationWindow : IUiWindow
{
event EventHandler SomethingMustBeDone;
}
You could use a custom event that is declared in your UserControl. Then your form needs to handle this event and call the method you want to call. If you let the UserControl access your form, you are hard-linking both with each other which decreases reusability of your UserControl.
For example, in TempCalib:
public delegate void OkClickedHandler(object sender, EventArgs e);
public event OkClickedHandler OkClicked;
private void OkButton_Click(object sender, EventArgs e)
{
// Make sure someone is listening to event
if (OkClicked == null) return;
OkClicked(sender, e);
this.Hide();
}
in your mainform:
private void Mainform_Load(object sender, EventArgs e)
{
_tempCalib.OkClicked += CalibOkClicked;
}
private void CalibOkClicked(Object sender, EventArgs e)
{
StartTemp();
}
You create an event in your usercontrol and subscribe to this in the mainform.
That is the usual way.
Form1 Code:
UserControl1 myusercontrol = new UserControl1();
public void TabClose(Object sender,EventArgs e)
{
int i = 0;
i = tabControl1.SelectedIndex;
tabControl1.TabPages.RemoveAt(i);
}
private void Form1_Load(object sender, EventArgs e)
{
myusercontrol.Dock = DockStyle.Fill;
TabPage myTabPage = new TabPage();
myTabPage.Text = "Student";
myTabPage.Controls.Add(myusercontrol);
tabControl1.TabPages.Add(myTabPage);
myusercontrol.OkClick += TabClose;
}
UserControl1 Code:
public delegate void OkClickedHandler(Object sender, EventArgs e);
public partial class UserControl1 : UserControl
{
public event OkClickedHandler OkClick;
public UserControl1()
{
InitializeComponent();
}
private void button3_Click(object sender, EventArgs e)
{
if (OkClick == null) return;
OkClick(sender, e);
}
}
Try this:
From user control try this:
MainForm form = this.TopLevelControl as MainForm;
form.TempCommand();
I have a program that has a parent form which then creates a child form. Upon clicking the updateButton within the child form, I want the searchButton within the parent form to fire.
However I get an error for protection reasons. I have tried setting everything Public just to see, still wont work for me.
Error 1 'SalesSystem.SystemForm.searchButton' is inaccessible due to
its protection level SalesSystem\UpdateForm.cs 111 20 SalesSystem
This is what I have so far.
Parent Code
namespace SalesSystem
{
public partial class SystemForm : Form
{
public SystemForm()
{
InitializeComponent();
}
protected void searchButton_Click(object sender, EventArgs e)
{
//search code
}
private void updateButton_Click(object sender, EventArgs e)
{
try
{
UpdateForm upForm = new UpdateForm(resultBox.SelectedItems[0].Text, dbdirec, dbfname);
upForm.ShowDialog(this);
}
catch (Exception)
{
//
}
}
}
Child Code
namespace SalesSystem
{
public partial class UpdateForm : Form
{
public UpdateForm(string selectedPerson, string dbdirec, string dbfname)
{
InitializeComponent();
}
private void updateButton_Click(object sender, EventArgs e)
{
//do stuff
SystemForm parent = (SystemForm)this.Owner;
parent.searchButton.PerformClick();
this.Close();
}
}
}
Your searchButton button control is set to private by default in WinForm. You've said you set everything to public but I assume you mean you've set everything in the code you've posted to public. There are a few ways to fix this. The direct fix would be to simply go to Visual Studio designer, select the button, and set its Modifier property to internal or public.
However, it seems you're closing your form straight after so I'd just have my parent form subscribe to the FormClosing event of the form.
UpdateForm upForm = new UpdateForm(resultBox.SelectedItems[0].Text, dbdirec, dbfname);
upForm.FormClosing += (s, o) =>
{
//your code for what the parent class should do
};
upForm.ShowDialog(this);
If you're not closing the form then you can create your own event handler that your parent form subscribes to.
You have 2 options:
create a public void search() method in your parent form. Then, instead of accessing the the button on the parent form and invoking its click event, you run the search code directly. The new method is not tied to a GUI element and accessing it from a different form is no problem.
The better solution is to create a delegate. A delegate is an execution target that will be assigned at run time. The parent form still has a public void search() method. And when it creates the child form, it will pass the name of that function as parameter. The child form has no knowledge about the parent form (as opposed to the first option where the child MUST know that there is a method called search()). When it is time to inform whoever created the child form, the delegate is called. This is a small example:
public partial class SystemForm : Form
{
public delegate void dSearch();
public SystemForm()
{
InitializeComponent();
}
protected void searchButton_Click(object sender, EventArgs e)
{
search();
}
private void search()
{
//search code
}
private void updateButton_Click(object sender, EventArgs e)
{
try
{
UpdateForm upForm = new UpdateForm(resultBox.SelectedItems[0].Text, dbdirec, dbfname, search);
upForm.ShowDialog(this);
}
catch (Exception)
{
//
}
}
}
And the child form:
public partial class UpdateForm : Form
{
private SystemForm.dSearch _target;
public UpdateForm(string selectedPerson, string dbdirec, string dbfname, SystemForm.dSearch target)
{
_target = target;
InitializeComponent();
}
private void updateButton_Click(object sender, EventArgs e)
{
//do stuff
_target();
this.Close();
}
}
You should use the "Model View Controller" or "Model View Presenter" pattern to approach this kind of thing.
Each form should only be concerned with displaying its contents to the user. When it comes to responding to UI events such as button clicks, each form (i.e. each "View") should simply raise an event which informs the controller/presenter that something has happened.
The controller/presenter should then respond appropriately. Then the logic that wires together different forms (such as the parent and child forms in your example) is encapsulated in the Controller class. Such logic does not really belong in either of the forms.
I wrote an example that demonstrates a simple design to do this sort of thing in another answer some time ago. Rather than copy/paste it all here, I'll just give you a link to it:
How to make Form1 label.text change when checkbox on form2 is checked?
You'll have to scroll down to see my answer. It's broadly similar to what you're doing; hopefully it will make sense to you! Follow the instructions to make a test application and run it to see what happens.
I'm tired and might be missing something but that is correct behaviour.
Your child form does not directly inherit from your parent form.
Your parent form has a protected level, so only it and classes that extend it can access the method.
2 solutions:
Change your child form to:
public partial class UpdateForm : SystemForm
Change method to public
public void searchButton_Click(object sender, EventArgs e)
You could expose a Search Event from your UpdateForm and subscribe to this event in the SystemForm
namespace SalesSystem
{
public partial class SystemForm : Form
{
public SystemForm()
{
InitializeComponent();
}
protected void searchButton_Click(object sender, EventArgs e)
{
//search code
}
private void updateButton_Click(object sender, EventArgs e)
{
try
{
UpdateForm upForm = new UpdateForm(resultBox.SelectedItems[0].Text, dbdirec, dbfname);
upForm.OnSearch += Search;
upForm.ShowDialog(this);
}
catch (Exception)
{
//
}
}
private void Search(string searchParameter)
{
....
}
}
namespace SalesSystem
{
public delegate void SearchEventHandler(string searchParameter);
public partial class UpdateForm : Form
{
public event SearchEventHandler OnSearch;
public UpdateForm(string selectedPerson, string dbdirec, string dbfname)
{
InitializeComponent();
}
private void updateButton_Click(object sender, EventArgs e)
{
//do stuff
OnSearch("SearchThis");
this.Close();
}
}
}
I'm trying to call methods from class "Form1" from an other class.
Here's my Code
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
MessageBox.Show("loaded");
orders.ObjectForScripting = new ScriptInterface();
}
private void webBrowser2_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { }
private void button1_Click_1(object sender, EventArgs e) { }
}
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public class ScriptInterface
{
public void callMe(string currid)
{
MessageBox.Show(currid);
// the following throws security error
Form1.webBrowser2.Navigate("http://www.mywebpage.com/client/index.php?id="+currid);
}
}
}
INFO: I have 2 WebBorwsers. I'm catching events from webBrowser1 for updating webBrowser2.
My problem is, that i cannot call the webbrowser2 methods outside from Form1.
Any Ideas how i can solve this problem?
Your WebBrowser components are not static (this is a good thing), therefore you cannot refer to them directly off of Form1 as your code sample is attempting to do. You must obtain a reference to a Form1 instance and then you can call methods on them so long as they are marked public. Depending on your needs it is probably even better to just pass along a reference directly to your WebBrowser components
Perhaps something like this:
orders.ObjectForScripting = new ScriptInterface(this.webBrowser2);
...
public class ScriptInterface
{
private WebBrowser _browser;
public ScriptInterface(WebBrowser browser)
{
_browser = browser;
}
public void callMe(string currid)
{
_browser.Navigate("http://www.mywebpage.com/client/index.php?id="+currid);
}
}
Form1 in:
Form1.webBrowser2.Navigate(...)
Is not an object, but it is your type. You need to create an instance of your class, or if you prefer, create an object to be able to call it's method:
Form1 form = new Form1();
form.webBrowser2.Navigate(...)
On top, your method are flagged private, which mean they can only be call from inside your instanced. You should flag them public if you want other object to be able to call them.
public void webBrowser2_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { ... }
Or if you don't want to create an instance, you can declare this method as being static
public static void webBrowser2_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { ... }
But you won't be able to access the fields that this class define unless they are static too.
I have a DataGridView in Form1 and I'm using this code to display another form called Generator:
private void button1_Click(object sender, EventArgs e)
{
Form gen = new Generator();
// Form gen = new Generator(Form this); //* I tried this but is not working *//
gen.Show();
}
In the Generator form I need to read or modify something in the datagridview which is in the Form1.
public partial class Generator : Form
{
public Form myForm;
public Generator()
{
InitializeComponent();
}
public Generator(Form frm)
{
myForm = frm;
}
private void button1_Click(object sender, EventArgs e)
{
myForm.mydatagridview.! // this is not working
}
}
How can I resolve this problem, so I can manipulate the DataGridView from the Generator form?
Form 1:
private void button1_Click(object sender, EventArgs e)
{
Form gen = new Generator(this.mydatagridview);
gen.Show();
}
Generator Form:
DataGridView _dataGridView;
public Generator(DataGridView dataGridView)
{
InitializeComponent();
this._dataGridView = dataGridView;
}
private void button1_Click(object sender, EventArgs e)
{
this._dataGridView...! // this will work
}
Things that you must do, and know (just tips, you are not forced to do these but I believe you will be a better programmer if you do! ;)
Always call InitializeComponent() in all form constructors. In your sample you didn't call it in one of the constructors.
C# knows only information of the type you have passed. If you pass a Form, then you only get Form properties (i.e. the properties of type Form), not the properties of your own form.
Try to encapsulate things. Do not pass a whole form to another form. Instead, pass things that you would like to use on the other form.
A few things are going on here.
You have to use the constructor of Generator that take in a form as a parameter.
You have to expose the datagridview as a public or internal property on the form that you will pass into Generator.
The normal Form class will not know about this property, so you should cast the variable appropriately.
You should call the default constructor of Generator when the other constructor is used to make sure everything is initialized correctly. See code sample below.
Something like this should work:
public class Generator
{
private MyForm myForm;
public Generator()
{
InitializeComponent();
}
public Generator(MyForm frm) : this() // DON'T FORGET THIS()
{
myForm = frm;
}
private void button1_Click(object sender, EventArgs e)
{
myForm.MyDataGridView... // Yay, it works!
}
}
public class MyForm : Form
{
public MyForm()
{
InitializeComponent(); // a datagridview is created here, say "datagridview1"
}
public DataGridView MyDataGridView
{
get { return datagridview1; }
}
}
And then in your button click event (which I assume is defined somewhere in MyForm):
private void button1_Click(object sender, EventArgs e)
{
Form gen = new Generator(this);
gen.Show();
}
The easiest way from there is to open the designer for the DataGridView (myDataGridView) on Form1 and set the Modifiers property from private to internal or public
This will let you call myForm.myDataGridView from the Generator form.