This may be an X-Y problem. Please don't hesitate to tell me if I'm completely off-base here.
First, a simplified example of the kind of situation I am thinking of.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace XXXXXXX
{
public class AbstractOperation : INotifyPropertyChanged
{
public enum OpState { Init, Running, Aborted, Completed, Errored };
OpState privateOperationState;
public OpState OperationState
{
get => privateOperationState;
private set
{
if(privateOperationState!=value)
{
privateOperationState = value;
OnPropertyChanged();
}
}
}
public bool IsRunning => OperationState == OpState.Running;
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
public class BackgroundOperator
{
AbstractOperation whatever;
public bool IsRunning => whatever.IsRunning;
public AbstractOperation.OpState OperationState => whatever.OperationState;
}
}
AbstractOperation is to be a base class representing some multi-step operation that takes significant time to perform. It will expose the status of it's operation through some properties.
BackgroundOperation is a class that will take an AbstractOperation and run it in a background thread, passing through some of the status properties. I want to be able to bind some UI element properties to these operations so that, for example, a certain control is disabled while the operation is running. I understand that the INotifyPropertyChanged interface is necessary for bindings like this to work.
If I implement the PropertyChange event on just one property like this, will the notification automatically cover other properties that refer to this property in their body? Does it work only within the class, or does it still work with another class that owns an instance of the notifying class? Do I need to do some special code to link the referring properties to the original property's notification? Or am I deep into X-Y land here and should implement some other way of binding UI controls to the status of my operation?
If I implement the PropertyChange event on just one property like this, will the notification automatically cover other properties that refer to this property in their body?
What happened when you tried it? Did you get property change notification for other properties?
Does it work only within the class, or does it still work with another class that owns an instance of the notifying class?
It doesn't do that at all, so it won't do it in any other class.
Property change notification isn't magic. It just raises the event, setting the name value in the event args object to the one you passed in to the OnPropertyChanged() method (in this case, implicitly via the [CallerMemberName] attribute).
All that said, using properties like this isn't necessarily the best way to deal with disabling commands. You don't say what API you're actually using, but a common one that uses this sort of pattern is WPF. It uses ICommand bindings for commands. The ICommand.CanExecute() method should be used to indicate whether a command is valid at a given time. ICommand.CanExecuteChanged should be raised when the value for that method changes. This is typically done by whatever code begins an operation or changes some state that would render the command invalid at that time. The same code would then change the CanExecute() state back to valid when it's done.
The exact mechanism for changing the command state and raising its event depends on how you implement the command. There are lots of examples out there, which you should review. See what works best for you.
If you are using some other API, it may or may not have a similar mechanism. It's not possible to know what the best answer along those lines would be, since that information is not available in your question.
Related
I have an object that gets passed to an interface, I would like for the concrete sitting behind that interface to perform some action every time one of the object's members changes state. In other words, I have some object that contains an integer. When the value of that integer changes, I would like for my concrete class sitting behind that interface to do some work.
Now, I could probably do something like this by having a thread that's sitting in the wait state and performs the action once some pulse is done using a monitor. But, I was wondering if the C# language had the inherent support for such a thing. Such that, when the object's member changes state the action will automatically be performed. I know that this may not be possible, and if there is an alternative solution I would like to hear that. Or, does the thread thing sound like a good idea?
You should implement INotifyPropertyChanged, also inherit your interface after INotifyPropertyChanged. Then introduce properties for all state ralated things and always in setter methods fire PropertyChanged event.
This requires some boilerplate code but it is very reliable solution. You can make your properties virtual and use IoC containers such as Unity to implement boilerplate for you.
After the implementation is done you simply subscribe to PropertyChanged event of object by using += operator.
myWatchedObject.ProperyChanged += listener.DependentObjectChangeHandler;
Encapsulate state of an object using a setter property.
Add more code to the setter property to raise an event or call a method.
The simplest way would be properties:
class MyClass
{
private int _MyInteger;
public int MyInteger
{
get { return _MyInteger; }
set { _MyInteger = value; /* insert your "do some work" code here */ }
}
}
I attempted to implement my own simple event aggregator recently. I got a lot of inspiration from the event aggregator article on MSDN. There is one thing that I notice about the event aggregator on MSDN is the events are actually classes on their own. This isn't really a bad thing at all. However, I just find it awkward to always create a new empty class for every single little event.
The reason I find it awkward is because of the need to create a class for every single granular event. A mouse click event, for instance, would have double_click, single_click, left_click, right_click, etc. And all of these are going to have a class of its own. It gets messy after a while.
So in my own implementation, I thought I could make it in such a way where the ClickEvent is a class, but all the granular events related to the Click event would then be "types" of the ClickEvent. In this case, the "types" are enum. The usage would look something like this:
//Publisher
eventAggregator.GetEvent<ClickEvent>.Publish(ClickEventType.Double_Click, eventArgs);
//Subscriber
eventAggregator.GetEvent<ClickEvent>.Subscribe(ClickEventType.Double_Click, handlerMethod);
However, I'm not sure if this implementation defeats the whole purpose of having a strongly typed event? Now, it seems like the ClickEvent is merely a container for the different event enum types.
Yes it does (seem like a container that is) - your handler will fire regardless of the click type and there will be some code required in the handler to determine the type of click, which makes things a little messier.
If your issue is mostly the organisation of the files/classes and keeping the code tidy, why not just create the click events as nested classes within a main click class
e.g.
public static class ClickEvents // Prevent instantiation
{
public class SingleLeft { }
public class SingleRight { }
public class DoubleLeft { }
public class DoubleRight { }
// Are there any more click events possible?!
}
eventAggregator.GetEvent<ClickEvents.SingleLeft>.Publish();
Aside from that, it's the uniqueness of the type that determines the event signature, and therefore multiple types are required to satisfy this particular implementation
At least the above keeps your handler code clean
void HandleLeftClick()
{
}
vs
void HandleClick(ClickArgs e)
{
if(e.ClickType == ClickType.Left)
{
}
}
Edit:
Also remember that you can subscribe multiple events to the same handler if you want to handle more than one click type:
eventAggregator.GetEvent<ClickEvents.SingleLeft>.Subscribe(HandlerMethod);
eventAggregator.GetEvent<ClickEvents.SingleRight>.Subscribe(HandlerMethod);
(this would work in the rare situation that the subscriber didn't care which mouse button was clicked)
I think you missed one possibility. You see, you don't have to create a new class for each notification. Instead, you are free to reuse classes but carry some additional state of arbitrary complexity inside.
public class MouseClickNotification {
public bool IsDoubleClick;
public MouseButton ClickedButton;
// any additional stuff
This way it is you who precisely define the granularity of your notification model.
I am trying to understanding the Event Aggregator pattern from an architecture and design view point. I have never used Prism in WPF before, but I'm studying how it works on MSDN.
It seems to me that for every event, the user has to create a new event object that extends the CompositePresentationEvent. It also appears that the new event object has no functionality other than those it inherited from (it usually has no code for itself).
So for example:
A AddNewStuffEvent would look like:
public class AddNewStuffEvent : CompositePresentationEvent<Object> {} //The end of the class
For a HealthChangeEvent:
public class HealthChangeEvent: CompositePresentationEvent<Object> {} //The end of the class
For a BookFlipEvent:
public class BookFlipEvent: CompositePresentationEvent<Object> {} //The end of the class
For a BookCloseEvent:
public class BookCloseEvent: CompositePresentationEvent<Object> {} //The end of the class
And this can go on forever for every little small event for BookOpenEvent, BookTearEvent, etc. So, in a particular namespace folder, there will be a whole ton of event classes, and the Event Aggregator is going to be loaded with all these event objects during runtime. That's, every little small event needs an empty class? Is this how it works? What could be a better way for this?
Yes, every event type needs its own class, which you have to define.
It also appears that the new event object has no functionality other than those it inherited from
The purpose is simply to provide strong typing for the event. This makes it easier to write code to subscribe to them. Ie, the subscribing code can be written like:
aggregator.GetEvent<AddNewStuffEvent>().Subscribe(Handler);
This is a preferable approach to alternatives, such as reliance on "magic strings" in the form of say aggregator.GetEvent("AddNewStuffEvent").Subscribe(Handler) (which could not be verified at compile time.
I have class that has two properties
public List<ChildMember> ChildMember
{
get
{
if (_ChildMember == null)
{
_ChildMember = this.UserRole == EUserRole.SalesExecutive ? this.GetMembers(this.LogonName, this.FilterByMID) : this.GetChildMembers();
}
return _ChildMember;
}
set
{
_ChildMember = value;
}
}
public int FilterByMID{ get; set; }
Essentially what I need to do is refresh the ChildMember list every time FilterByMID value is changed. I know I can set the this.ChildMember = null before updating the value of FilterByMID but I was wondering if this would be a good place to use INotifyPropertyChanged or perhaps a better way? Any help would be appreciated.
P.S.: GetMembers() method has the logic to check for 0s and -ve values in case it is bothering you :)
P.S.: This class lives in a class library but is used by ASP.NET WebApplication not WCF/WPF ... I noticed a lot of posts for WCF / WPF when I was searching for INotifyPropertyChanged so just wanted to clarify.
If you're only doing this once in this class I wouldn't mind bringing in INotifyPropertyChanged as you would have to make the notification in your setter for FilterByMID and then wire up an event handler in which you'd update the other property.
However, if you have multiple classes and instances needing to observe changes in properties on each other, it might be a more suitable way.
There're also some frameworks which are interesting in this regard. Some examples are the Reactive Extensions, Rx.NET, and the (built on the former) Reactive UI, which has a component not only suitable for user interface programming.
You should just clear the field in the FilterByMyID setter.
INotifyPropertyChanged allows you to notify someone else that a property changed.
Using it directly within your class will just make your code more complicated.
I read some events tutorial and just do not get what is the benefit in simple code like this..method should be used the same way:
class Bulb
{ public delegate void handler();
public event handler Glowing;
...
Glowing+=SomeMethod;
private void TurnOn
{
Glowing();
}
private void SomeMethod
{
}
}
Simply Events allow others using your code to perform some custom Implementation they want when that Event occurs (when Bulb is Glowing).
Simply calling your method won't tell anybody that something has happened.
Events are very basic Element of any Event Driven Programming
If your program doesn't need to tell about an event you don't need to implement such Functionality. However having such functionality has benefits.
For Example when using a List Class you dont know when an Item got added to it (if at some point some other code does that) but in a ObservableCollection you get notifications when Items are Added or Removed.
An event is a message sent by an object to signal the occurrence of an action. The action could be caused by user interaction, such as a mouse click, or it could be triggered by some other program logic.
The idea is that a different class which can hold Three different Bulbs can get notified by the event (if it implements a handler) that the light has been turned on and is Glowing.
So the benefit does not reside in the simply class but in what ever classes/objects are going to be holding/using instances of the Bulb class.
Hope that made some sense :)
Events over methods become handy when you have a class dependency that needs to know or be notified about a stateful change:
public class Lamp
{
Bulb inThelamp = new Bulb();
inTheLamp.Glowing += myLampMethod;
// If these arguments have been defined for this event that is
public void myLampMethod(object sender, EventArgs e)
{
// Code to react to the light suddenly being on
}
}
This allows the Lamp class to recognize that something has turned the bulb on. In many cases it will be through some action in the Lamp (click, pushknob, etc). But in some cases it could be an external class that calls a public Bulb property directly without using the Lamp itself (such is if(PowerCompany.BillsPaid) Lamp.BulbInTheLamp.TurnedOn();). This is all assuming that the modifiers are set to allow this kind of access.
The point is that it allows notification of an occurrence rather than requiring that a particular method be called manually each time you want an action to occur.