WinForms AutoSave To Database (vs. Save Button) - c#

I'm writing a WinForms (C#) using Entity Framework. application
Currently, I have a big fancy Save Button on my form that works just as you'd hope and expect it to.
I have been asked to change the application to save automatically as the the user changes each field.
I know I can do this by adding code to the Value_Changed event in each of my controls. But is there an easier way? There are a large number of controls on this form. Some way to overload the OnChange event for multiple control types (Text, DropDown, CheckBox, RadioButton)?

In the form's constructor, loop through all of its child controls (this.Controls) recursively and add the (same) callback method to the ValueChanged event for each of them. That will associate it with each control on the form regardless of any changes to the form in the future.
using System;
using System.Diagnostics;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
foreach (Control c in this.Controls)
{
c.Validated += C_Validated;
}
}
private void C_Validated(object sender, EventArgs e)
{
Debug.Print($"{sender.GetType().FullName} had Validated event called");
}
}
}

Related

Windows form doesn't show Form_Load in visual studio

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}
}
I am watching tutorial where Form1_Load() is included
I am watching tutorial where Form1_Load() is included, is there another way to include TextBox items by coding?
CSharp and VB.NET are a bit different on how to write event handlers. In your case, you need to tell the forms designer you want to handle the .Load event.
Find the properties window in the designer for the form, and click on the lightning bolt.
Now the properties window displays all the events that the form can trigger. Find Load and double-click on the space next to it.
The designer will now generate the Form1.Load() method you are missing
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
An alternative way to do this same thing.
In the form constructor type this.Load += and then press the [Tab] button.
Visual studio will fill in the code needed to handle the event wit the option to rename the event handler
A third way of handling the Load event
My preferred way is to override the OnLoad() method in the form.
Type override OnLoad inside the class, and IntelliSense is going to prompt you the method to override. Select OnLoad and press [Tab].
Now you can write the same code you would have before, but inside the OnLoad() method which gets called automatically every time the .Load event triggers.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// Write code here
}
}
Yes in the 20+ years of WinForms programming and VisualStudio development some redundancies have developed. It is not a bad thing, as VS needs to accommodate different coding styles.
There is a 4th way, that applies to VB.NET and involves the Handles keyword which makes more logical sense IMHO than the way C# does things, but that is just me.
You can "wire up" events via code.
Here's an example with the Load() event of the Form:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Load += Form1_Load;
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
This can be done with any control and event, but it's easier to do via the IDE as described by Jeroen van Langen. If you're creating dynamic controls (created at run-time) then this is the way to do it.
Go to your form designer and make sure the form control self is selected. press F4 for the properties control. Press on the lightning icon for events and search for the Load event.

How to call a function inside a form from a user control (C# Winforms)

So I have user control I want to hide/send to back and I want to call the public function in my form where the user control is, from the control itself.
I have a button in the user control with the following code:
mainboard MAIN = new mainboard(); // mainboard is a form to call to.
MAIN.PastLockScreen(); // PastLockScreen is a public void inside mainboard
When I click the button the public function in mainboard does not get called. There are no errors, what am I doing wrong, and how can I call a function in a form from a user control?
void inside mainboard
public void PastLockScreen()
{
lockscreen1.SendToBack(); // lockscreen1 is the usercontrol that this function gets called from
}
The void is being referenced but not called?
Edit: I have done some investigating and turns out that my timers I have in any form or control, also dont work. But buttons on the actual form itself do work. (and yes I did do timerName.Start(); when the form/control loads.)
Solved the issue above, my timers needed to display time, which the time string I defined inside the class instead of inside the timer.tick
From within the UserControl, just cast ParentForm to type mainboard:
// .. form within the UserControl that is CONTAINED by form mainboard ...
private void button1_Click(object sender, EventArgs e)
{
mainboard MAIN = this.ParentForm as mainboard;
if (MAIN != null)
{
MAIN.PastLockScreen();
}
}
Note that this is a TIGHTLY COUPLED approach that limits your use of the UserControl to only mainboard.
A better approach would be to make the UserControl raise some kind of custom EVENT that the mainboard form then subscribes to. When the event is received then the form itself would run the appropriate method. This would mean you could potentially utilize the UserControl in a different form without changing any code within it. This latter approach would be LOOSELY COUPLED.
Try This
In Form1
to Show the Form2
Form2 frm2 = new Form2();
frm2.Show();
To call the method do you want
Form2 cmd = new Form2();
cmd.PastLockScreen();
In Form2
public void PastLockScreen()
{
this.SendToBack();
}

binding custom control to an external button

I have a custom control that i'm using in an external application. I want to bind a click event of a random button in the application to add data to my control.
Is something like that even possible?? Basically what i was thinking was creating a property in my control that allows a developer to add a button control to it at design time. And then when the application is run, any clicks registered on the button will be forwarded to a method in the custom control to add data.
Is this doable? if so, can someone explain what needs to be done exactly?
You can create a property of type Button in your custom control. Then when you put an instance of custom control on the designer, for that property, you will see a dropdown that shows all Button instances on the form which you can select one of them. It's enough to add a method to click event of the button in setter of the property:
using System;
using System.Windows.Forms;
public class MyControl : UserControl
{
private Button addButton;
public Button AddButton
{
get { return addButton; }
set
{
if (addButton != null)
addButton.Click -= new EventHandler(addButton_Click);
addButton = value;
if (addButton != null)
addButton.Click += new EventHandler(addButton_Click);
}
}
void addButton_Click(object sender, EventArgs e)
{
MessageBox.Show("Add Button Clicked!");
}
}
When you put it on designer, for AddButton property, a list o available buttons on the form will be shown. it's enough to choose one of them, then the behavior which you want (here in the example, showing the message box) will attach to click event of that button.

User Control Events and Overrides

I have a User Control for typical CRUD like actions on my WinForm app.
Validate, Insert, Update, Clear, Cancel, and Delete.
On every form I put this on I end up adding the click event, ucPersonNav.btnValidate.Click += new EventHandler(btnValidate_Click);, for every button.
What I am wondering is can I have the Events be on the User Control themselves and just have them point to a Method that I override on a Form by Form basis?
Something like this -->
namespace psUserControls
{
using System;
using DevExpress.XtraEditors;
public partial class ucVIUCCDwithWhoDoneIt : XtraUserControl
{
public ucVIUCCDwithWhoDoneIt()
{
InitializeComponent();
}
private void btnValidate_Click(object sender, EventArgs e)
{
ValidateEvent();
}
}
}
And then on a Form have this -->
void ValidateEvent()
{
if (dxValidDiagnosis.Validate())
{
if (planDiagnosisID != 0)
{
ucNavDiagnosis.btnUpdate.Enabled = true;
ucNavDiagnosis.btnDelete.Enabled = true;
}
ucNavDiagnosis.btnInsert.Enabled = true;
}
}
Is this feasible? Is it idiotic? If Yes then No then what steps do I need to take to make this work?
Thanks
i think .. not a bad idea..
but the approach would be very specific to your application.
we can have an enum for CRUD buttons - 6 enum items as you specified.
We can have a single event handler - delegate which takes above enum as a parameter.
Write an event (MyButtonClickedEvent) for this delegate which will be fired on each button clicked event.
on your control, on each button clicked event you can fire this event with respective enum item as a parameter.
e.g. on Validate button click, fire MyButtonClickedEvent with parameter as validate enum item.
On Inser button click, fire same MyButtonClickedEvent with parameter as Insert enum item.
This way you will have to handle single event on your form. You will be firing different events from your control. But this is to be done only once. On your form you will write a just one single handler - Method. In this method, you can differentiate depending on the enum type. .Net supports enum in switch-case construct. So you can easily identify the opteration that you have to perform.
All the users of your control will find it easier as they have to handle just one event. They will ignore the cases in switch construct which they are not interested.
Hope this helps.
You just need to define ValidateEvent as an event. In your UserControl:
public event EventHandler ValidateEvent;
On the form:
ucNavDiagnosis.ValidateEvent += new EventHandler(<name of event handler function>);
It's probably not a great idea to be accessing the buttons of the UserControl directly, however.

Benefits of using Inherit Forms Controls

I tryed to create new components from one base Windows Form, also I found difficulties when I worked with toolstrip components, for example :
how to bind a datagrid.datasource on a child form using events from a button (clicks) on the parent toolstrip?
I have to use some snippets on each child form for doing this, btw why?
// btnSearch
//
this.btnSearch.Click += new System.EventHandler(this.btnExec_Click);
private void btnExec_Click(object sender, EventArgs e)
{
//do stuff
}
Thanks
EDIT: I also know about modifiers issue :
I mean, I have to replace the toolstripbutton with a common button, also have to add more code on designer class (base form) :
grpCommonControls.Height = 20;
dtTScomponent = new ToolStripControlHost(grpCommonControls);
dtTScomponent.Alignment = ToolStripItemAlignment.Right;
toolStrip1.Items.Add(dtTScomponent);
tssbExporta.Alignment = ToolStripItemAlignment.Left;
toolStrip1.Items.Add(tssbExporta);
I was needed to add a simple toolstrip with some toolstrip controls on my base form, but the designer dont allow me to work correctly with those (I cannot route the events from toolstripbutton to my child forms as an example)
When you create a form that inherits another form that contains different controls, there are not event handlers automatically hooked up for you. Instead you need to do that as in your code sample. Another approach is to attach that event handler in your base form, and then have the base form expose events that you can listen to. Example:
In the base form:
public event EventHandler ExecInvoked;
private void btnExec_Click(object sender, EventArgs e)
{
OnExecInvoked(e);
}
protected virtual void OnExecInvoked(EventArgs e)
{
EventHandler evt = ExecInvoked;
if (evt != null)
{
evt(this, e);
}
}
Then, in your inherited form, you can either set up an event handler for the ExecInvoked event (you can probably do this using the events list in the property grid), or you can override the OnExecInvoked method:
protected override void OnExecInvoked(EventArgs e)
{
base.OnExecInvoked(e);
// do what the form should do when Exec is invoked
}
This way you have encapsulated the internals of the base form, so that the child form does not know what kind of control that raises the event (it could even be several different controls leading to the same event being raised), but the base form still provides a clear point where the child form can react on it.
To be able to change properties and subscribe to events of controls inherited from your parent Form (or UserControl), the parent form should set those controls' Modifiers property to protected (or, in general, to any value such that fields generated for controls in parent form are visible to the child form). The default value for Modifiers is private.

Categories

Resources