Encapsulating an event handler - c#

I have developed an event handler that monitors a serial port and parses the bytes returned to get a temperature value. My question is, how do I get this value out to the rest of my programme? The event, and the new value, is inside my event handler, and thus the rest of my solution doesn't know about it. I can't define a method outside to request it, because the rest of the solution doesn't know when new data comes in via the event handler and changes the variable.
I could, I suppose, write it to a new line of a text box on a form somewhere, but this seems to fly in the face of encapsulation.
Is there a sensible way to do this?

It sounds like you should probably expose another event that the rest of your system could subscribe to - TemperatureChanged, for example. Then you make your event handler (which is attached to the serial port) raise the TemperatureChanged event when it notices that the temperature has changed.
Your TemperatureChanged event should have an appropriate type so that the subscriber only has to care about the temperature change, not the raw data that you've interpreted. (It should probably be an EventHandler<TEventArgs> of some description.)
Another option is that you could just have a Temperature property, and implement INotifyPropertyChanged accordingly, raising the event when you change the property in your event handler. This is broadly equivalent, but more general purpose - lots of code (particularly in WPF) knows how to handle INotifyPropertyChanged.

Related

WPF RoutedCommand/RoutedEvent who/what raises the event?

I'm trying to understand how WPF implements the routed commands which, internally, are themselves implemented by routed events. In the UIElement class definition, we find this piece of code:
EventManager.RegisterClassHandler(type, CommandDevice.CommandDeviceEvent, new
CommandDeviceEventHandler(UIElement.OnCommandDeviceThunk), false);
From there on, the UIElement.OnCommandDeviceThunk handler will pass along all the information through arguments of functions it calls in its body which themselves do the same until it reaches the CommandBinding.Executed event which we subscribe to, thus executing our response code.
What I can't seem to find, and would like to understand, is who raises the CommandDevice.CommandDeviceEvent?
When, for example, I have linked a ButtonBase subclass object's Command property to an ApplicationCommands command, does it raise the CommandDeviceEvent in some way and how does it do it?
I understand the GlobalEventManager holds scores of lists of event handlers, but I haven't yet understood who raises the events to trigger those handlers?
When, for example, I have linked a ButtonBase subclass object's Command property to an ApplicationCommands command, does it raise the CommandDeviceEvent in some way and how does it do it?
The ButtonBase class calls the ExecuteCommandSource method of an internal CommandHelpers class when it is clicked: https://referencesource.microsoft.com/#PresentationFramework/Framework/System/Windows/Controls/Primitives/ButtonBase.cs,c0949dd81fca07f3,references
This method then executes the actual command, i.e. the object that the ICommand property returns: https://referencesource.microsoft.com/#PresentationFramework/Framework/MS/Internal/Commands/CommandHelpers.cs,518e4547841e704d

Event handling in MVVM

In MVVM, Model will usually have the data model, view is UI (XAML) which is further binded to the properties VM, ViewModel which typically inherits INotifyPropertyChanged.
When it comes to event handling, are there any specific pattern to handle all events on UI?
For Ex: Lets say if we have save/new/close button or some other button... and desired goal is when user does some operation and clicks on any of the button, control should go to code behind and should perform desired operation... how should I make sure that I have done the event handling in proper manner? and which interface I should use / when and how?
like we have ICommand interface/Relay command/Delegate command... I am not clear with this..
Thanks in advance for your response to my query...
Amit, if you are planning to hook up buttons, the accepted way is to use an implementation of ICommand (my personal preference is RoutedCommand). If you are aiming of to raise and handle events, have a look at Event Aggregators which is based on Publisher/Subscriber pattern.
In this, you will register a method (message handler) to ‘listen’ to a message (event) that matches a pattern. Once you done that, you can raise/publish messages (events) and when a match is found, the correct handler will gat raised
PRISM framework by Microsoft has done a good job of implementing event aggregate pattern
http://msdn.microsoft.com/en-us/library/ff921122(v=pandp.20).aspx
Hope this is useful

When to Call Method after Property Change

I have a User Control that contains a list of items and I raise an event when the currentIndex changes, also, when it changes, I must call two other methods two verify and change the appearance of the Control (change an Image and block/unblock some buttons).
What I want to know, mostly out of curiosity because it is already working, is when is it more appropriate to call these two methods?
Should I call them within the CurrentIndex property per se? Should I call them within the OnCurrentIndexChanged(...)? Should I handle the event within the class and do it there?
I'll assume you've implemented the standard event generating pattern and made OnCurrentIndexChanged protected virtual so that a derived class can override the method and alter the event generation and/or handling.
Unfortunately that requires reading tea leaves, why would anybody want to override the method? And more seriously, how could overriding the method break your control when they do? That's awfully hard to guess at for anybody that doesn't know the code well, not exactly easy for you either. The principle to apply here, used in the .NET framework code as well, is to do as little as possible. Just raise the event, nothing else. Which minimizes the odds of breakage when the derived class does something silly, but entirely common, like not calling base.OnCurrentIndexChanged.
The behavior of your controls is an implementation detail of your UserControl. So change their properties in your CurrentIndex property setter, then call OnCurrentIndexChanged(). Anybody that derives from your class can override that behavior, if necessary. And nothing goes wrong when they forget to call your OnCurrentIndexChanged() method. But do note that you need to make the control variables protected instead of private. So they can override the behavior, if they need to.
And don't hesitate to just not use a virtual method at all if this is too spooky for you. It's not common to have to accommodate hundreds of thousands of programmers with your controls :)
In the user control, I would have a property that represents the selected item. Then, during the setter of the object, raise the event method to change your user control. That way, in the future, if you need to add more listeners, you just need to add another handler in the setter method. This is pretty common in MVVM applications and is pretty maintainable.
Because your UserControl acts as a ListControl, you need to implement two events and two properties.
public event System.EventHandler SelectedIndexChanged;
public event System.EventHandler SelectionChangeCommitted;
public int SelectedIndex {
get;
set;
}
public T SelectedItem { // Where T is whatever your type is
get;
set;
}
SelectedIndexChanged should always be used for actions that always need to be triggered when your selected index is changed. SelectionChangeCommitted should only be triggered when the user physically changes the selection. The separation between the two is an important distinction, and most controls in .NET follow this pattern (eg. ComboBox), but may not use the same name for the events.
Now, with that said, if the controls you need to change properties for are also within the same user control, then you should of course handle that within the user control code in the appropriate event. Otherwise, the code should be orphaned to whoever implements the user control (eg. a form or another user control) by subscribing to the event and doing the work there.
The order really depends on your requirements, but SelectedIndexChanged should always be raised (but not more than once per change as that would introduce strange behavior), and again SelectionChangeCommitted should only be raised by the user (eg. setting SelectedIndex or SelectedItem).
A good rule of thumb is if your internal stuff MUST happen before the user knows about it, call SelectedIndexChanged first, then SelectionChangeCommitted. If it doesn't matter, either or. Changing the order later on could result in breaking changes in whoever implements the control, so make sure your decision is solid.
The difference between the two is SelectedIndex and SelectedItem would be updated by things like clearing your list internally, adding new items, et cetera, but does not necessarily mean it was a physical user action that should result in both your events firing.
Hope this helps.

Raise custom events in C# WinForms

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).

problems designing event driven communication

Im struggling a bit with a design issue. Im making a very simple gui system in c#. The code is meant to be reusable so Im looking for the most flexible solution here. The solutions I come up with seem to all have their drawbacks.
For simplicity lets pretend there are three classes: controller, button and the client code. The client code is the code using the gui system. It creates the controller and calls Update() on it. The controller creates a bunch of button instances and calls Update() on them. The buttons draw themselves and check for mouse clicks.
Now the problem is how do I get the fact that a button was clicked to the client code?
Option 1: Add GetButton(string name) to the controller class. The client code can then subscribe to the events defined in the button class => GetButton("but").MouseUpEvent += MouseUpHandler; The drawback to this is that this exposes Button.Update() which is, and should only, be used by the controller.
Option 2: Have the controller subscribe to all buttons and the client code subscribe to the controller. The drawback here is more parsing code in the client code as now all events are funneled through the controller, so the client has to check which button sent each event. I prefer to setup the flow of events in the initialization phase like in option 1.
Option 3: Add Subscribe/Unsubscribe methods to the controller for each event (SubscribeMouseUp(string buttonName, GUIDelegate del) etc.) Drawback is the controller api grows quickly.
So right now Im leaning towards option 1, but GetButton returns an interface (IClientButton maybe) that only declares the events, thereby hiding Update() from the client, but Im not sure if this is how interfaces are supposed to be used.
Any insight is appreciated.
Bas
Presumably this is an issue because Update() is public?
Presuming you've organized your button and controller into the same namespace would using internal protection suit your needs?
interface can be used that way, INotifyPropertyChanged is an interace with 1 item which is an event.
what about using RoutedEvents?
There's a 4th, maybe more popular option.
Have a dispatcher as a central location to register/unregister with. All event receivers register a callback with the dispatcher. All event generators send their events to the dispatcher.
It keeps the API cleaner and helps to untangle object referencing.
In your Controller, add two events - ButtonCreated and ButtonDestroyed.
public event EventHandler<ClientButtonEventArgs> ButtonCreated;
public event EventHandler<ClientButtonEventArgs> ButtonDestroyed;
The ClientButtonEventArgs is simply an EventArgs wrapper around your IClientButton interface.
Have your client code subscribe to both of these events. When the Controller creates a new button, have it fire the ButtonCreated event. The client code can then subscribe to the necessary Button events when it receives the event notification. Similarly, the Controller will fire the ButtonDestroyed event as necessary, allowing the client code to unsubscribe from the Button's events.
In this way, the entire sequence is event-driven. The client code reacts to the creation and destruction of a Button, which it seems like is what you're after.

Categories

Resources