I am developing a windows mobile application, and I want to do something after a form (a loading screen) is displayed to the user.
normally, I have a Form.Shown event, but with the .net compact framework v3.5, I can't find this event.
Does anyone know of an equivalent to the Shown event or a simple workaround I could use? I don't want to do my own multi-threading if I can help it.
The only thing I can think of would be a bit of a hack, when your form is shown, if it has a default control then it will receive the focus. The Focus event will fire during the initial load before the form is shown, but will be fired the second time when it is visible. put a boolean in the Activate event that is set with the first Activates, then test in the default controls Got Focus event.
Other option would be to use a Timer. Set the Interval to something like 10, start it at the end of your Form Load event and then run your startup specific code.
private void Form1_Load(object sender, EventArgs e)
{
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop();
//Do something
}
An example per Hans's Comment:
public partial class Form1 : Form
{
public delegate void DoWorkDelegate();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
BeginInvoke(new DoWorkDelegate(DoWorkMethod));
}
public void DoWorkMethod()
{
//Do something
}
}
Related
I have a dataGridView on the form, then I added a checkBox programically.
I added it to dataGridView.Controls list. Now I would like to run the method c_CheckedChanged every time when event of changing the checkbox is raised.
I did it in as in the code below, but it does nothing when I change the status of the checkBox.
How can add methods to the events of elements from dataGridView.Controls list?
I know I can use DataGridViewCheckBoxCell instead of standard checkBox, but it is not the solution I am looking for. I am trying to learn how to create events of custom controls in Controls.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
var cb=new CheckBox();
dataGridView1.Controls.Add(cb);
(dataGridView1.Controls[0] as CheckBox).CheckedChanged += c_CheckedChanged;
}
private void c_CheckedChanged(object sender, EventArgs e)
{
var a=1;
}
}
I used the code var a=1; to put here breakpoint and check if the method is done.
But it is not.
Could you help, please?
Regards,
Kris
Straight to the problem:
In my main form, i have a three buttons that open three different forms. I will show you how it is built.
MainForm (Here is three buttons, with the three different form names on them)
Theory -> Click this button to open TheoryForm
Tasks -> Click this button to open TasksForm
Compete -> Click this button to open CompeteForm
Inside my TasksForm is a button that is going to open the TheoryForm. Here is my code:
public partial class TasksForm : Form
{
public TasksForm()
{
InitializeComponent();
}
public void TheoryButton_Click(object sender, EventArgs e)
{
Form TheoryForm_Child = new TeoriForm();
TheoryForm_Child.Show();
}
//Add some code here so that when `TasksForm` closes, the `TheoryForm_Child` closes too.
}
And what I can't figure out is, when the TasksForm is closed, the TheoryForm is supposed to close as well, right now it doesn't.
Try declaring the variable to your TheoryForm outside of the TheoryButton.Click event handler and then use it in your TaskForm.FormClosing event handler to close it.
public partial class TasksForm : Form
{
private Form TheoryForm_Child;
public TasksForm()
{
InitializeComponent();
FormClosing += TaskForm_FormClosing;
}
public void TheoryButton_Click(object sender, EventArgs e)
{
TheoryForm_Child = new TeoriForm();
TheoryForm_Child.Show();
}
public void TaskForm_FormClosing(object sender, FormClosingEventArgs e)
{
if(TheoryForm_Child != null)
TheoryForm_Child.Close();
}
}
Just because TasksForm is creating TheoryForm does not mean that when TasksForm is closed, so will TheoryForm. Instead, you should close it explicitly like by handing the closed event in your TasksForm, like this.
public partial class TasksForm : Form
{
Form _TheoryFor_Child = new TheoryForm();
public TasksForm()
{
InitializeComponent();
Closed += TasksForm_Closed;
}
private void TasksForm_Closed(object sender, EventArgs e)
{
_TheoryFor_Child.Close();
}
private void TheoryButton_Click(object sender, EventArgs e)
{
_TheoryFor_Child.Show();
}
}
You need to connect parent and child form in some way.
For example in giving the child form the parent form as owner.
Simply call
TheoryForm_Child.Show(this);
There is a really simple solution. You should use the other version of Show method like this:
Form TheoryForm_Child = new TeoriForm();
TheoryForm_Child.Show(this);
That's all. Then your form will be owner of theory form. So it will automagically destroy Theory form after closing itself.
More reading here: https://msdn.microsoft.com/en-us/library/szcefbbd%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
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'm writing a program that can take quite a bit to load(5-30 seconds). I'm wanting to have a form that starts with a marquee style progress bar, so that the user knows there's something being done.
public FrmMain()
{
var loading = new FrmLoading();
loading.Show();
InitializeComponent();
// other start up code here
loading.Close()
}
Now, loading pops up just fine. The problem is that the label and the progress bar show as nothing, and it almost looks like they are crashing. I've looked into the BackgroundWorker, but, honestly, I don't fully comprehend how to make that work for me. I tried to follow the tutorials and examples at:
BackgroundWorker Basics in C#
C# BackgroundWorker
ProgressBar
BackgroundWorker Class
But my head just isn't grasping it. Is there any other way to get the form to load properly? Thanks for any and all help.
EDIT
My BackgroundWorker attempt included me creating a function which performed all the actions that were done in my FrmMain. So, I had:
public FrmMain()
{
Loading = new FrmLoading();
Loading.Show();
backgroundWorker1.RunWorkerAsync();
}
private void FormLoading()
{
// Initialize and loading elements of the form
InitializeComponent();
}
private void BackgroundWorker1DoWork(object sender, DoWorkEventArgs e)
{
FormLoading();
}
private void BackgroundWorker1RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Loading.Close();
}
But I kept getting NullReferenceException on the backgroundWorker1.RunWorkerAsync();
An little-known or often-forgotten framework library is Microsoft.VisualBasic. You can use it with C# apps. Just add a Reference ... and this class. It handles all background worker threading and the rest.
public class MyApplication : WindowsFormsApplicationBase
{
private static MyApplication _application;
public static void Run(Form form)
{
_application = new MyApplication{ MainForm = form };
_application.Run(Environment.GetCommandLineArgs());
}
protected override void OnCreateSplashScreen()
{
this.SplashScreen = new MySplashScreenForm();
}
}
Finally, change the app launch under Program.Main() from:
Application.Run(new Form1());
to
MyApplication.Run(new Form1());
If you aren't familiar, this class also offers more features like Single-Instance Handling that are definitely worth a look.
Perhaps this will help:
Add a:
Shown += new EventHandler(Form1_Shown);
after your InitializeComponent();.
And add:
void Form1_Shown(object sender, EventArgs e)
{
Refresh();
}
Also, if you didn't subscribe to the BackgroundWorker1DoWork event handler in the Designer, you'll have to add:
backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
What I ended up doing may not be elegant, but it accomplished what I needed.
public FrmMain()
{
InitializeComponent();
backgroundWorker1.RunWorkerAsync();
var loading = new FrmLoading();
loading.ShowDialog();
}
private void BackgroundWorker1DoWork(object sender, DoWorkEventArgs e)
{
DbQuery();
}
private void BackgroundWorker1RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Loading.Close();
}
This brings up my loading form so that it has focus and fully loads. Since I called the DoWork before I called the ShowDialog(), the BackgroundWorker continues to work. Once DbQuery() is done, it calls the BackgroundWorker1RunWorkerCompleted(), which closes my FrmLoading and continues on with my program. Thanks to everyone who posted.
I want to popup/show a dialog when ever my user control is displayed/shown. But I couldn't find any such event. What options do I have and what would I have to do to implement it myself?
I'm using DevExpress XtraUserControl.
Thanks.
Register to the Activated event of the main form.
public Form1()
{
InitializeComponent();
this.Activated +=new EventHandler(Form1_GotFocus);
}
public void Form1_GotFocus(object sender, EventArgs e)
{
//your payload here
}
Note that if you close a dialog and return to the form, the event is fired again.