Raise custom events in C# WinForms - c#

I have some Events I created on my own and was wondering on how to raise them when I want.
Probably my application design is also messed up, might take a look at that if you like.
This is the Structure
ProgramContext
- Form MainWindow
+ Control TextBox
+ Control Button
+ ...
In this case, the MainWindow.TextBox holds some information that is updated quite often at runtime. So, I somehow need it to refresh itself when I want to (so it can reload its data from the database, where the it's stored)
I tried hooking an EventHandler to its Validating-Event, but that didn't seem to do the trick.
So, basically I have a method that reloads the data in ProgramContext
DataTable table = _adapter.GetData();
foreach (DataRow row in table.Rows)
{
MainWindow.TextBox.Text += table.Text.ToString();
}
That needs to be done whenever another method (that writes new data into table) is executed.
Any ideas?

Edit : It seems your question is more about hooking into a specific event, but FWIW below is how to fire custom events in general.
Handling the TextBox Changed Event
From what I understand, you want an external party to monitor events raised from a textbox on a Form and then to reload data on another form?
A quick and dirty would be to make the Form TextBox public and then others could subscribe to this event
MainForm.textBox1.TextChanged += new System.EventHandler(this.textBox1_TextChanged);
OR, in more recent versions of C#:
MainForm.textBox1.TextChanged += this.textBox1_TextChanged;
Adding Your own Custom Event
Another, cleaner way would be to raise a custom event, - e.g. MyDataChangedEvent below. This will allow you to abstract away the fact that the changes are coming from a textbox at all.
// Assuming you need a custom signature for your event. If not, use an existing standard event delegate
public delegate void myDataChangedDelegate(object sender, YourCustomArgsHere args);
// Expose the event off your component
public event myDataChangedDelegate MyDataChangedEvent;
// And to raise it
var eventSubscribers = MyDataChangedEvent;
if (eventSubscribers != null)
{
eventSubscribers(this, myCustomArgsHere);
}
You might also look at the Ent Lib Composite Application Block and Smart Client Software Factory - this has a very flexible event broking / pub sub mechanism for synchronising across UI "SmartParts" (controls, forms dialogs etc) in a loose-coupled fashion. (CAB is now very dated).

Related

Xamarin Forms Event Bubbling and Invoking Operations on a Custom Renderer

I am creating a custom Xamarin Forms control that contains three buttons (1,2,3) inside a view. Let's just call it a GaugeView for the sake of this example. Here is how it is currently setup:
The GuageView has a custom renderer on both iOS and Android called GuageViewRenderer.
The GuageView exposes event handlers for Clicked1, Clicked2, and Clicked3.
The GuageView exposes ICommand properties for Click1, Click2, and Click3.
The problem is, I need to fire the event handlers from the custom renderer because only the native platform control knows when one of the buttons has been pressed. How do you bubble the events back up to the GuageView, which is where the shared code lives?
I was planning to wire up the commands and the event handlers down inside the custom renderer, but I'm having a heck of a time with it since events can only be fired from within the original class (GuageView).
Is there a better way to structure this? The main thing I am trying to do is expose the platform native guage and wire its buttons up so the event handlers in the shared code (GuageView) gets the event firings.
Right, you can't raise events outside of the class that declares them. So you'll have to add a method to GaugeView that will raise the events. I would also have that same method invoke the commands as well. So in GaugeView
public void RaiseClick1() {
var clicked1 = Clicked1;
if (clicked1 != null)
clicked1(this, EventArgs.Empty);
if (Command1 != null && Command1.CanExecute(Command1Paramter))
Command1.Execute(Command1Parameter);
}
Then in GaugeViewRender whenever you need to notify the view that a button was clicked:
Element.RaiseClick1();
Late answer but maybe for the future: You can raise the click event of a button from outside using the IButtonController interface.
The Xamarin.Forms.Button class implements this interface which provides one single method: SendClicked
By casting your Xamarin.Forms element in the renderer (this.Element) to IButtonController you're able to call this method and raise the clicked event of the Xamarin.Forms.Button.
I also created a blog post about this topic: http://software.fauland.cc/?p=5637

Remove and later re-add all event handlers associated with a groupbox in C# winforms

Is there a way to get the collection of handlers associated with a groupbox in C# winforms?
For the cases the checked statuses need to be changed programatically (not by the user), I need to turn off the handlers so other parts of the program do not fire. It is tedious to do this by hand for many handlers.
Is there a working code version of this pseudocode that does not work below?
foreach(Control C in parent.groupBox1.Controls)
{
C.disableHandlers()
}
//change controls handlers would have interfered with
foreach(Control C in parent.groupBox1.Controls)
{
C.enableHandlers()
}
It is possible to use some crazy reflection code to do this, but you don't want to do that because you'll invariably run into "well I still want to keep this event just not the others".
I recommend making a class that contains a list of add-listener delegates and a list of remove-listener delegates, and then iterate through and execute each delegate at the appropriate times.

Winform app, force execute OnLoad Event when focus is on another tab

I have a WinForm app, the form has TabControl, control has three tabs tabPage1,tabPage2,tabPage3.
The Tab 'tabPage3' is hosting a User defined control which internally has one or more child controls.
Now my problem lies in tabPage3,
I know it is a pure Winforms behavior, until your parent is not activated child controls Onload event won't fire.
I have a requirement to force the Onload event to fire when the focus is on tabPage1, tabPage2. Is there any way to force the Onload event to fire.
I have already visited following links but didn't find any clue. Link Link Link
This is a very unusual requirement, strongly smells like an XY problem. The Load event is heavily over-used in Winforms, a side-effect of it being the default event for a Form or UserControl. One of the behaviors inherited from VB6, the Load event was a big deal in that language. What you want can easily be accomplished by not giving Winforms a choice:
public UserControl3() {
InitializeComponent();
CreateHandle();
}
The CreateHandle() call does the forcing, OnLoad will immediately run. But do be aware that this happens very early, too early to do the kind of things that you'd really want to use OnLoad() or the Load event for. Which are rather limited, it is only truly necessary to discover the actual Location and Size of the control. Anything else belongs in the constructor. Surely including the code that you now run in OnLoad().
Strongly favor using the constructor instead.
I had a similar problem for a previous project, for my needs I managed to just iterate over every tab page in the forms constructor (or possibly OnLoad I can't remember) and then reset the index back to 0 before ever showing the end user.
Something similar to:
for(int i = 1; i < tabControl.TabCount; i++)
tabControl.SelectTab(i);
tabControl.SelectTab(0);

WinForms control event handler gets removed when selecting another one and thus it becomes 'unreferenced'

Question about the WinForms designer and how to customize behavior. What I've seen multiple times is that when you select a different event handler for a button it will remove the old one (as in ,the code) when it becomes unused.
I want to avoid this behavior but can't find configuration for this. Anyone a hint? Thanks!
Update
Since multiple comments question the actions that trigger this in the first place, I'd like to point out that it has mostly hit me during refactoring of an existing code base.
There is no configuration for this. The designer does the Right Thing, it only removes event handlers that have no code. As soon as you put something in the method body then it preserves what you've written and generates a new method. This ensures that you don't lose code and ensures that you don't have dead methods littering your code.
Beware that adding more than one event handler for a control's event in the same class (form) makes very little sense. You should just merge the code of the handlers. This also ensures that you won't have any surprises, the order in which multiple subscribers for the same event runs is fairly unpredictable. The designer only supports a single event handler, simply because it doesn't have any way to track more than one.
This is just the way the Designer works - you can't change it.
What you can do to work around your problem is to add your event handlers in code, rather than in the designer:
public Form1()
{
InitializeComponent();
this.button1.Click += new EventHandler(button1_Click);
this.button1.Click +=new EventHandler(button1_Click2);
}
I must point out that I question the need for two separate event handlers.

Custom event on object to change button state

I have 3 buttons on my Data Entry form, OK, APPLY, CANCEL.
This form is used to edit a doctor's details, things like first name, phone # etc...
I have one object doctorObj which at any given time is either empty (a new doctor) or an object pulled from a Linq query.
I deep clone the doctorObj to EditCopyDoctor which is of the same type but used for form editing (so if Cancel is hit, the database do not need to update).
What I want to achieve is observe the EditCopyDoctor for changes against the original doctorObj so
If(doctor.Changed() && doctor.IsNotNew)
{
ApplyButton.Enabled = true;
}
else
{
ApplyButton.Enabled = false;
}
So I thought writting an event to trigger when something changed on EditCopyDoctor is the best way to do it but I'm not sure how.
I can of course put the ApplyButton.Enabled code in the TextChanged events from the form but I was wondering if there are any quicker ways to do this, I don't really want to do this as there are 10+ textbox and other controls.
Since your "Doctor" type sounds like it's generated by LINQ to SQL/Entities you should find that it already implements the INotifyPropertyChanged interface. Therefore, you should just need to watch the PropertyChanged event and act accordingly.

Categories

Resources