Creating a base Windows Forms form - c#

I have done a base form for my window app but not sure is this correct or is there a better way to improve it.
My purpose:
Simplify my code at UI form
Create CRUD button to be inherited.
Question:
How do I implement interface with the 4 button events at the UserForm.cs by right clicking the UserForm:BaseForm. Currently I have to manually write all 4 button event to override.
My BaseForm seem to be empty. Can I put the messageBox.show("succcess") at my baseForm? Meaning to say that after run the UserForm.cs, it will run back to BaseForm. This can save up a few lines of code at userform.
Should I put my logger at the baseForm too?
My baseForm.cs
public BaseForm()
{
InitializeComponent();
}
public virtual void btnSave_Click(object sender, EventArgs e)
{
}
public virtual void btnDelete_Click(object sender, EventArgs e)
{
}
public virtual void btnNew_Click(object sender, EventArgs e)
{
}
public virtual void btnReset_Click(object sender, EventArgs e)
{
}
My UserForm.cs inherit baseForm
public override void btnSave_Click(object sender, EventArgs e)
{
if (!IsValidated()) return;
BindValueToObject();
try
{
user.Add();
bindingSource.Add(user);
MessageBox.Show("Success");
}
catch(Exception ex)
{
MessageBox.Show("failed");
Logger.Error(typeof(UserForm), ex.ToString());
return;
}
}
public override void btnDelete_Click(object sender, EventArgs e)
{
base.btnDelete_Click(sender, e);
}
public override void btnNew_Click(object sender, EventArgs e)
{
base.btnNew_Click(sender, e);
}
public override void btnReset_Click(object sender, EventArgs e)
{
base.btnReset_Click(sender, e);
}

1 - At the moment the methods in your base form is declared as virtual. This means that it is optional for any derived classes to override the methods. Therefore you won't be notified asking to override them. If this is your desired behavior then you will have to manually override the methods by either writing the code yourself or getting your IDE to generate the methods for you. However, if this is not the desired behavior and you would in fact like to force all derived classes to implement these methods, then you should declare them as abstract.
2 - Any calls to those methods will trigger the overridden methods in the derived class (if it exists) and thus the code in your base class will never get executed. If you're interested in both executing the code in the derived- and the base class then you should issue a call to the base method like this
public override void btnReset_Click(object sender, EventArgs e)
{
// do form specific stuff here
someButton.Text = String.Empty;
// then invoke base method
base.btnReset_Click(sender, e);
}
3 - If you're going to do general logging for the form, then putting it in the base class would be a good idea. However, remember always to invoke the base method call in any overridden method.

Related

Why I dont see a MessageBox? c#

I have just created a program with that code:
class INF2 : Form1
{
public void checkBox1_CheckedChanged(object sender, EventArgs e)
{
Zaznacz();
}
private void Zaznacz()
{
if (checkBox1.Checked == true)
{
MessageBox.Show("Dot Net Perls is awesome.");
}
}
}
where the function inherits from:
public void checkBox1_CheckedChanged(object sender, EventArgs e)
{
}
inside the Form1 ( it's a normal checkBox) and I want to see a messagebox when I press the checkbox by the INF2 class (necessarily inheritance)
Read your compiler warnings.
You created a new method that happens to have the same name as the base method, but doesn't actually have anything to do with it.
You need to use virtual and override.

C# Calling a method

I have a form with multiple instances of a user control on it.
I've assigned the following:
Switch.armySwitchCloseButton.Click += armySwitchClose;
So when one of those instances is pressed, I call the following method:
void armySwitchClose(object sender, EventArgs e)
The above method has a bunch of additional code in it which isn't required for here.
Now what I need to do is from another button, call this above function from every instance.
How can I do this?
Many Thanks
In constructor of each user control you can pass the same instance of some object who knows how to run this method
void armySwitchClose(object sender, EventArgs e)
Then, you call this method inside each event method, for ex:
Public Class UserControl(){
private MakeEvent makeEvent;
Public MyClass(MakeEvent makeEvent)
{
this.makeEvent = makeEvent;
Switch.armySwitchCloseButton.Click += armySwitchClose;
}
void armySwitchClose(object sender, EventArgs e)
{
makeEvent.armySwitchClose(sender,e);
}
}
Public Class MakeEvent() {
void armySwitchClose(object sender, EventArgs e)
{
//the real implementation
}
}
Hope this solve your problem.
Oh, I think I get your problem wrong... When you click in one button all the other events in others UC must be triggered, right? This problem can be solved with the Observer Pattern
Public Interface IObserver
{
void armySwitchClose(object sender, EventArgs e);
}
Public UserControl1: Observer
{
void armySwitchClose(object sender, EventArgs e)
{
//implementation UC1
}
}
Public UserControl2: Observer
{
void armySwitchClose(object sender, EventArgs e)
{
//implementation UC2
}
}
In button UC:
Public UserControlButton
{
private List<IObserver> observers;
public void addObserver(IObserver observer)
{
observers.Add(observer);
}
public void button_clickedEvent(object sender, EventArgs e)
{
foreach(IObserver observer in observers)
{
observer.armySwitchClose(object sender, EventArgs e);
}
}
}
In form with all buttons you call addObserver adding each user control.

C# Form UserControl OnClick events

I've created a custom user control for a windows form that will operate similar to a button (and please don't suggest that I just use a button, because I will be storing data in this user control), but I can't figure out how to get the OnClick() event to fire. I've sifted through a handful of tutorials and looked at a few similar questions on the site, but I can't seem to get the event to fire off - so I'm either doing something wrong or everyone posted incorrect code (I hope it isn't the latter)
In my custom control.cs,
namespace MobCreator {
public partial class MOBSample : UserControl {
public MOBSample() {
InitializeComponent();
}
protected override void OnMouseUp(MouseEventArgs e) {
this.BorderStyle = BorderStyle.FixedSingle;
base.OnMouseUp(e);
}
protected override void OnMouseDown(MouseEventArgs e) {
this.BorderStyle = BorderStyle.Fixed3D;
base.OnMouseDown(e);
}
public event EventHandler ButtonClick;
private void OnButtonClick(object sender, EventArgs e) {
// invoke UserControl event here
if (this.ButtonClick != null) this.OnButtonClick(sender, e);
}
}
}
And in my form.cs,
private void MobCreatorForm_Load(object sender, EventArgs e) {
UserControl1.ButtonClick += new EventHandler(this.CustomEvent_Handler);
}
private void CustomEvent_Handler(object sender, EventArgs e) {
Console.WriteLine("Click");
}
However, when I run the program my console never outputs "Click".
Check this link on MSDN: it is a simple Event tutorial, you should be able to adapt it to your scenario.
At a first look, what you are probably missing is a Delegate for your event.
Try this
private void MobCreatorForm_Load(object sender, EventArgs e)
{
CustomEvent_Handler(null,null);
}
private void CustomEvent_Handler(object sender, EventArgs e)
{
Console.WriteLine("Click");
}

Calling a base page method from a user control in asp.net

I have been trying to find a good answer to this question, but can't seem to find one. I have an ASP.NET page that derives from a base page, like this:
public partial class MainPage : MyBasePage
{
protected void Page_Load(object sender, EventArgs e)
{
var loginTime = GetLoginTime(); // This works fine
}
}
And the base page:
public partial class MyBasePage: Page
{
}
protected DateTime GetLoginTime()
{
// Do stuff
return loginTime;
}
Now I have a user control on that page that needs to call my method...Like this:
public partial class TimeClock : UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
var loginTime = GetLoginTime(); // This does not work!
}
}
As you can see, I cannot call my base method, for obvious reasons. My question is, how can I call this method from my user control? One work around I've found is like this:
var page = Parent as MyBasePage;
page.GetLoginTime(); // This works IF I make GetLoginTime() a public method
This works, if I make my function public instead of protected. Doing this doesn't seem like a very OOP way to tackle this solution, so if someone can offer me a better solution, I'd appreciate it!
TimeClock inherits from UserControl, not from MyBasePage so why should TimeClock see the Method GetLoginTime()?
You should keep your UserControl out of your Page stuff. It should be decoupled in OOP speak. Add properties to set values and delegates to hook into events:
public partial class TimeClock : UserControl
{
public DateTime LoginTime{ get; set; }
public event UserControlActionHandler ActionEvent;
public delegate void UserControlActionHandler (object sender, EventArgs e);
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button_Click(object sender, EventArgs e)
{
if (this.ActionEvent!= null)
{
this.ActionEvent(sender, e);
}
}
}
Page
public partial class MainPage : MyBasePage
{
protected void Page_Load(object sender, EventArgs e)
{
var loginTime = GetLoginTime();
TimeClock1.LoginTime = loginTime;
TimeClock1.ActionEvent += [tab][tab]...
}
}
(this.Page as BasePage).MethodName()

I cannot extend (subclass) DataReceivedEventArgs?

I'm trying to extend DataReceivedEventArgs so that I can pass in additional data to a class that is extending Process. Pretty much rather than just get Data from a process when hooking up to Process.OutputDataReceived, I would like to pass in a control for it to write to.
When trying to extend DataReceivedEventArgs I get errors:
The type 'System.Diagnostics.DataReceivedEventArgs' has no constructors defined
public class DataReceivedArgsWithControl : DataReceivedEventArgs
{
public Control ControlAdded { get; set; }
}
How can I add another property to this Args? I've extended EventArgs itself because it has a constructor, but not sure how to extend this Args.
I suspect that you can't because the constructor is Internal. Perhaps a better approach would be to wrap the DataReceivedEventArgs inside your EventArgs derived class.
class MyDataReceivedEventArgs : EventArgs
{
DataReceivedEventArgs _inner;
public MyDataReceivedEventArgs(DataReceivedEventArgs inner, object extraProperty)
{
_inner = inner;
ExtraProperty = extraProperty;
}
public object ExtraProperty { get; private set;}
public DataReceivedEventArgs DataArgs
{
get
{
return _inner;
}
}
}
Of course, this might not be suitable if you need the polymorphism with DataReceivedEventArgs. If you have an event handler that is expecting a DataReceivedEventArgs then it won't work with the wrapper class. For example:
public void MyHandler(object sender, DataReceivedEventArgs e) { ... }
This could only receive a DataReceivedEventArgs instance or an instance of a derived type, which your wrapper is not. So it depends if you need to treat your custom EventArgs class is if it were a DataReceivedEventArgs anywhere.
UPDATE-
If you can't change the signature of the delegate you're using from public delegate void DataReceivedEventHandler(object sender, DataReceivedEventArgs e) then you can still subscribe using a method with the signature void MyEventHandler(object sender, EventArgs e) thanks to contravariance of delegate parameters and then check the actual type of the EventArgs parameter.
public void MyEventHandler(object sender, EventArgs e)
{
var dataEventArgs = e as MyDataReceivedEventArgs;
if(dataEventArgs != null
{
var extendedProperty = dataEventArgs.ExtraProperty;
var innerArgs = dataEventArgs.DataArgs;
}
}
The ideal option would be to redefine the delegate type to match your wrapper, but the above approach will work.

Categories

Resources