Prism - The subscribed event doesn't trigger - wpf

I have the following situation (I'm working on a WPF application but I don't think that's important):
Class A;
Class B that it is invoked from A;
A constructor:
public A(IEventAggregator eventAggregator){
_eventAggregator = eventAggregator;
Button = new DelegateCommand(f);
_eventAggregator.GetEvent<MyEvent>().Subscribe(handleMyEvent);
}
And at the bottom:
private void f()
{
//here I create a new instance of B with Autofac
var bootstrap = new Bootstrapper();
var container = bootstrap.BootStrap();
BInstance= container.Resolve<B>(new NamedParameter("id", "myId"),
new NamedParameter("action", "my_action"));
BInstance.Show(); //here in real I create a view that has a DataContext = B instance
}
Also, B constructor looks like this:
public B(IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
// some other stuff
}
In the B class at some point I want to trigger the event 'MyEvent' that I have subscribed in the A constructor. So, I do something like this:
private void f()
{
_eventAggregator.GetEvent<MyEvent>().Publish();
}
My problem is, simply, that the event doesn't trigger (the function handleMyEvent never perform its work).
Important thing:
if I replace this line in the f function (on A):
BInstance= container.Resolve<B>(new NamedParameter("id", "myId"),
new NamedParameter("action", "my_action"));
With:
BInstace = createB() // where createB is a Func<B>
it works without any problem. I really don't get why this is happening.
The main problem is that I must pass some parameters to the B ctor (that's not totally true, since I pass these parameters to another class that instantiate B but doesn't matter).
Note: I'm working with Autofac as dependencies injector and Prism for the events.

A and B in your setup work on different event aggregators. Of course, one doesn't know of the subscriptions of the other.
You have to create both A and B from the same container:
private void f()
{
BInstance = _container.Resolve<B>(new NamedParameter("id", "myId"),
new NamedParameter("action", "my_action"));
BInstance.Show(); //here in real I create a view that has a DataContext = B instance
}
For this to work, A needs the container:
public A(IEventAggregator eventAggregator, IContainer container){
_eventAggregator = eventAggregator;
_container = container;
}
But beware, injecting the container is a code smell, to say the least. If this a real app, create a factory class to produce your B instances.

Related

Unity3D - how to use arrays with custom inspector code?

I seem to be stuck in a catch 22 situation with the OnInspectorGUI method of Unity's UnityEditor class. I want to name array elements in the inspector for easy editing, currently I'm using, as per the documentation:
public override void OnInspectorGUI()
{
J_Character charScript = (J_Character)target;
charScript.aBaseStats[0] = EditorGUILayout.FloatField("Base Health", charScript.aBaseStats[0]);
}
In my J_Character script I initialise the aBaseStats array like so:
public float[] aBaseStats = new float[35];
The problem is that whenever I try to do anything in the editor (and thus OnInspectorGUI is called) I get an index out of range error pointing to the line
charScript.aBaseStats[0] = EditorGUILayout.FloatField("Base Health", charScript.aBaseStats[0]);
I'm guessing this is because my array is initialized on game start while the editor code is running all the time while developing.
How can I get round this situation?
Many thanks.
You have to initialize aBaseStats in an function that runs only once.
The code below is BAD:
public float[] aBaseStats = new float[35];
void Start(){
}
The code below is GOOD:
public float[] aBaseStats;
void Start(){
aBaseStats = new float[35];
}
Initialize it in an Editor callback function that runs once.
EDIT:
I don't know a Start callback function that will run before the OnInspectorGUI function(). The hack below should work.
public float[] aBaseStats;
bool initialized = false;
public override void OnInspectorGUI()
{
if (!initialized)
{
initialized = true;
aBaseStats = new float[35];
}
J_Character charScript = (J_Character)target;
charScript.aBaseStats[0] = EditorGUILayout.FloatField("Base Health",aBaseStats[0]);
}
As an addition to the answer by Programmer I would like to point you to the following:
http://docs.unity3d.com/ScriptReference/ExecuteInEditMode.html
This seems to be exactly what you are looking for in terms of functionality. (it runs the method even when playmode is not active)
using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
public class ExampleClass : MonoBehaviour {
public Transform target;
void Update() {
if (target)
transform.LookAt(target);
}
}

Autofixture, expected behavior?

Having a test similar to this:
public class myClass
{
public int speed100index = 0;
private List<int> values = new List<int> { 200 };
public int Speed100
{
get
{
return values[speed100index];
}
}
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var fixture = new Fixture();
var sut = fixture.Create<myClass>();
Assert.AreEqual(sut.Speed100, 200);
}
}
Would have expected this to work, but I can see why it's not. But how do I argue, that this is not a problem with AutoFixture, but a problem with the code?
AutoFixture is giving you feedback about the design of your class. The feedback is, you should follow a more object-oriented design for this class.
Protect your private state, to prevent your class from entering an inconsistent state.
You need to make the speed100index field, private, to ensure it remains consistent with the values List.
Here is what I see if I run debugger on your test:
Autofixture assigns a random number to speed100index field because it is public, and in your array there is nothing at point 53 (from my screenshot)
If you set speed100index to be private, Autofixture will not re-assign the number and your test will pass.

Dependecy properties that depend on other properties

Class C implements INotifyPropertyChanged.
Assume the C has Length, Width and Area propreties, where Area = Length * Width. A change in either might cause a change in area. All three are bound, i.e. the UI expects all three to notify of changes in their values.
When either Length or Width change, their setters call NotifyPropertyChanged.
How should I treat the calculated Area property? Currently the pattern I can think of is detecting in NotifyPropertyChanged whether the changed property is either Length or Width and, if such is the case, initiate an addional PropertyChanged notification for Area. This, however, requires that I maintain inside NotifyPropertyChanged the dependencies graph, which I feel is an anti-pattern.
So, my question is: How should I code dependency properties that depend on other dependency properties?
edit: People here suggested that Length and Width also call NotifyPropertyChanged for Area. Again, I think this is an anti-pattern. A property (IMHO) shouldn't be aware of who depends on it, as shouldn't NotifyPropertyChanged. Only the property should be aware of who it depends on.
This issue kept on bugging me, so I re-opened it.
First, I'd like to appologize for anyone taking my "anti-pattern" comment personally. The solutions offered here were, indeed, how-it's-done in WPF. However, still, IMHO they're bad practices caused, deficiencies in ther framework.
My claim is that the information hiding guide dictates that when B depeneds on A, A should not be aware of B. For exmaple, when B derives from A, A should not have code saying: "If my runtime type is really a B, then do this and that". Simiarily, when B uses A, A should not have code saying: "If the object calling this method is a B, then ..."
So it follows that if property B depends on property A, A shouldn't be the one who's responsible to alert B directly.
Conversely, maintaining (as I currently do) the dependencies graph inside NotifyPropertyChanged is also an anti-pattern. That method should be lightweight and do what it name states, not maintain dependency relationships between properties.
So, I think the solution needed is through aspect oriented programming: Peroperty B should use an "I-depend-on(Property A)" attribute, and some code-rewriter should create the dependency graph and modify NotifyPropertyChanged transparently.
Today, I'm a single programmer working on a single product, so I can't justify dvelving with this any more, but this, I feel, is the correct solution.
Here is an article describing how to create a custom attribute that automatically calls PropertyChanged for properties depending on another property: http://www.redmountainsw.com/wordpress/2012/01/17/a-nicer-way-to-handle-dependent-values-on-propertychanged/
The code will look like this:
[DependsOn("A")]
[DependsOn("B")]
public int Total
{
get { return A + B; }
}
public int A
{
get { return m_A; }
set { m_A = value; RaisePropertyChanged("A"); }
}
public int B
{
get { return m_B: }
set { m_B = value; RaisePropertyChanged("B"); }
}
I haven't tried it myself but I like the idea
When the Length or Width properties are changed you fire PropertyChanged for Area in addition to firing it for either Length or Width.
Here is a very simple implementation based on backing fields and the method OnPropertyChanged to fire the PropertyChanged event:
public Double Length {
get { return this.length; }
set {
this.length = value;
OnPropertyChanged("Length");
OnPropertyChanged("Area");
}
}
public Double Width {
get { return this.width; }
set {
this.width = value;
OnPropertyChanged("Width");
OnPropertyChanged("Area");
}
}
public Double Area {
get { return this.length*this.width; }
}
Doing it like this is certainly not an anti-pattern. That is exactly the pattern for doing it. You as the implementer of the class knows that when Length is changed then Area is also changed and you encode it by raising the appropriate event.
Then you should raise twice, in Length and Width property setters. One for the actual property and one for the Area property.
for example:
private int _width;
public int Width
{
get { return _width; }
set
{
if (_width == value) return;
_width = value;
NotifyPropertyChanged("Width");
NotifyPropertyChanged("Area");
}
}
People here suggested that Length and Width also call
NotifyPropertyChanged for Area. Again, I think this is an
anti-pattern. A property (IMHO) shouldn't be aware of who depends on
it, as shouldn't NotifyPropertyChanged. Only the property should be
aware of who it depends on.
This is not an anti-pattern. Actually, your data encapsulated inside this class, so this class knows when and what changed. You shouldn't know outside of this class that Area depends on Width and Length. So the most logical place to notify listeners about Area is the Width and Length setter.
A property (IMHO) shouldn't be aware of who depends on it, as
shouldn't NotifyPropertyChanged.
It does not break encapsulation, because you are in the same class, in the same data structure.
An extra information is that knockout.js (a javascript mvvm library) has a concept which accessing this problem: Computed Observables. So I believe this is absolutely acceptable.
Here is a possible implementation of an attribute:
public class DependentPropertiesAttribute : Attribute
{
private readonly string[] properties;
public DependentPropertiesAttribute(params string[] dp)
{
properties = dp;
}
public string[] Properties
{
get
{
return properties;
}
}
}
Then in the Base View Model, we handle the mechanism of calling property dependencies:
public class ViewModelBase : INotifyPropertyChanged
{
public ViewModelBase()
{
DetectPropertiesDependencies();
}
private readonly Dictionary<string, List<string>> _dependencies = new Dictionary<string, List<string>>();
private void DetectPropertiesDependencies()
{
var propertyInfoWithDependencies = GetType().GetProperties().Where(
prop => Attribute.IsDefined(prop, typeof(DependentPropertiesAttribute))).ToArray();
foreach (PropertyInfo propertyInfo in propertyInfoWithDependencies)
{
var ca = propertyInfo.GetCustomAttributes(false).OfType<DependentPropertiesAttribute>().Single();
if (ca.Properties != null)
{
foreach (string prop in ca.Properties)
{
if (!_dependencies.ContainsKey(prop))
{
_dependencies.Add(prop, new List<string>());
}
_dependencies[prop].Add(propertyInfo.Name);
}
}
}
}
protected void OnPropertyChanged(params Expression<Func<object>>[] expressions)
{
expressions.Select(expr => ReflectionHelper.GetPropertyName(expr)).ToList().ForEach(p => {
RaisePropertyChanged(p);
RaiseDependentProperties(p, new List<string>() { p });
});
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
protected virtual void RaisePropertyChanged(string propertyName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
protected void RaiseDependentProperties(string propertyName, List<string> calledProperties = null)
{
if (!_dependencies.Any() || !_dependencies.ContainsKey(propertyName))
return;
if (calledProperties == null)
calledProperties = new List<string>();
List<string> dependentProperties = _dependencies[propertyName];
foreach (var dependentProperty in dependentProperties)
{
if (!calledProperties.Contains(dependentProperty))
{
RaisePropertyChanged(dependentProperty);
RaiseDependentProperties(dependentProperty, calledProperties);
}
}
}
}
Finally we define dependencies in our ViewModel
[DependentProperties("Prop1", "Prop2")]
public bool SomeCalculatedProperty
{
get
{
return Prop1 + Prop2;
}
}

null reference exception error for my windows form app

I have a Setting.cs file containing the info
[Serializable]
public class Setting
{
public Setting() {}
public String defaultAlertTone = Path.GetDirectoryName(Application.ExecutablePath) + "\\Sounds\\applause-2.wav";
}
and my settingsForm retrieving the info through this code
Setting settingObject;
public SoundPlayer player;
public settingsForm(backgroundForm backgroundFormObject)
{
InitializeComponent();
this.backgroundFormObject = backgroundFormObject;
settingObject = backgroundFormObject.getSetting();
}
private void InitializeSound()
{
// Create an instance of the SoundPlayer class.
player = new SoundPlayer();
player.SoundLocation = settingObject.defaultAlertTone;
// Listen for the LoadCompleted event.
player.LoadCompleted += new AsyncCompletedEventHandler(player_LoadCompleted);
// Listen for the SoundLocationChanged event.
player.SoundLocationChanged += new EventHandler(player_LocationChanged);
}
Why is it that every time I run the app, there would be a null reference exception on the
player.SoundLocation = settingObject.defaultAlertTone;
the backgroundFormObject.getSetting(); is just a method to retrieve the setting object. the code for it are as follows
Setting settingObj = new Setting();
public Setting getSetting()
{
return settingObj;
}
The reasons could be
InitializeSound() is somehow running before settingsForm (not likely, but this would make the settingObject not initialized and refer to null).
If this is the complete code for Setting class, i don't see how calling new Setting() anywhere would make a difference. So use Setting settingObject = new Setting(); when you first define this property in the settingsForm class.
It is not the settingObject which is null.

How to share an Array between all Classes in an application?

I want to share an Array which all classes can "get" and "change" data inside that array. Something like a Global array or Multi Access array. How this is possible with ActionScript 3.0 ?
There are a couple of ways to solve this. One is to use a global variable (as suggested in unkiwii's answer) but that's not a very common approach in ActionScript. More common approaches are:
Class variable (static variable)
Create a class called DataModel or similar, and define an array variable on that class as static:
public class DataModel {
public static var myArray : Array = [];
}
You can then access this from any part in your application using DataModel.myArray. This is rarely a great solution because (like global variables) there is no way for one part of your application to know when the content of the array is modified by another part of the application. This means that even if your data entry GUI adds an object to the array, your data list GUI will not know to show the new data, unless you implement some other way of telling it to redraw.
Singleton wrapping array
Another way is to create a class called ArraySingleton, which wraps the actual array and provides access methods to it, and an instance of which can be accessed using the very common singleton pattern of keeping the single instance in a static variable.
public class ArraySingleton {
private var _array : Array;
private static var _instance : ArraySingleton;
public static function get INSTANCE() : ArraySingleton {
if (!_instance)
_instance = new ArraySingleton();
return _instance;
}
public function ArraySingleton() {
_array = [];
}
public function get length() : uint {
return _array.length;
}
public function push(object : *) : void {
_array.push(object);
}
public function itemAt(idx : uint) : * {
return _array[idx];
}
}
This class wraps an array, and a single instance can be accessed through ArraySingleton.INSTANCE. This means that you can do:
var arr : ArraySingleton = ArraySingleton.INSTANCE;
arr.push('a');
arr.push('b');
trace(arr.length); // traces '2'
trace(arr.itemAt(0)); // trace 'a'
The great benefit of this is that you can dispatch events when items are added or when the array is modified in any other way, so that all parts of your application can be notified of such changes. You will likely want to expand on the example above by implementing more array-like interfaces, like pop(), shift(), unshift() et c.
Dependency injection
A common pattern in large-scale application development is called dependency injection, and basically means that by marking your class in some way (AS3 meta-data is often used) you can signal that the framework should "inject" a reference into that class. That way, the class doesn't need to care about where the reference is coming from, but the framework will make sure that it's there.
A very popular DI framework for AS3 is Robotlegs.
NOTE: I discourage the use of Global Variables!
But here is your answer
You can go to your default package and create a file with the same name of your global variable and set the global variable public:
//File: GlobalArray.as
package {
public var GlobalArray:Array = [];
}
And that's it! You have a global variable. You can acces from your code (from anywhere) like this:
function DoSomething() {
GlobalArray.push(new Object());
GlobalArray.pop();
for each (var object:* in GlobalArray) {
//...
}
}
As this question was linked recently I would add something also. I was proposed to use singleton ages ago and resigned on using it as soon as I realized how namespaces and references work and that having everything based on global variables is bad idea.
Aternative
Note this is just a showcase and I do not advice you to use such approach all over the place.
As for alternative to singleton you could have:
public class Global {
public static const myArray:Alternative = new Alternative();
}
and use it almost like singleton:
var ga:Alternative = Global.myArray;
ga.e.addEventListener(GDataEvent.NEW_DATA, onNewData);
ga.e.addEventListener(GDataEvent.DATA_CHANGE, onDataChange);
ga.push(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "ten");
trace(ga[5]); // 5
And your Alternative.as would look similar to singleton one:
package adnss.projects.tchqs
{
import flash.utils.Proxy;
import flash.utils.flash_proxy;
public class Alternative extends Proxy
{
private var _data:Array = [];
private var _events:AltEventDisp = new AltEventDisp();
private var _dispatching:Boolean = false;
public var blockCircularChange:Boolean = true;
public function Alternative() {}
override flash_proxy function getProperty(id:*):* {var i:int = id;
return _data[i += (i < 0) ? _data.length : 0];
//return _data[id]; //version without anal item access - var i:int could be removed.
}
override flash_proxy function setProperty(id:*, value:*):void { var i:int = id;
if (_dispatching) { throw new Error("You cannot set data while DATA_CHANGE event is dipatching"); return; }
i += (i < 0) ? _data.length : 0;
if (i > 9 ) { throw new Error ("You can override only first 10 items without using push."); return;}
_data[i] = value;
if (blockCircularChange) _dispatching = true;
_events.dispatchEvent(new GDataEvent(GDataEvent.DATA_CHANGE, i));
_dispatching = false;
}
public function push(...rest) {
var c:uint = -_data.length + _data.push.apply(null, rest);
_events.dispatchEvent(new GDataEvent(GDataEvent.NEW_DATA, _data.length - c, c));
}
public function get length():uint { return _data.length; }
public function get e():AltEventDisp { return _events; }
public function toString():String { return String(_data); }
}
}
import flash.events.EventDispatcher;
/**
* Dispatched after data at existing index is replaced.
* #eventType adnss.projects.tchqs.GDataEvent
*/
[Event(name = "dataChange", type = "adnss.projects.tchqs.GDataEvent")]
/**
* Dispatched after new data is pushed intwo array.
* #eventType adnss.projects.tchqs.GDataEvent
*/
[Event(name = "newData", type = "adnss.projects.tchqs.GDataEvent")]
class AltEventDisp extends EventDispatcher { }
The only difference form Singleton is that you can actually have multiple instances of this class so you can reuse it like this:
public class Global {
public static const myArray:Alternative = new Alternative();
public static const myArray2:Alternative = new Alternative();
}
to have two separated global arrays or even us it as instance variable at the same time.
Note
Wrapping array like this an using methods like myArray.get(x) or myArray[x] is obviously slower than accessing raw array (see all additional steps we are taking at setProperty).
public static const staticArray:Array = [1,2,3];
On the other hand you don't have any control over this. And the content of the array can be changed form anywhere.
Caution about events
I would have to add that if you want to involve events in accessing data that way you should be careful. As with every sharp blade it's easy to get cut.
For example consider what happens when you do this this:
private function onDataChange(e:GDataEvent):void {
trace("dataChanged at:", e.id, "to", Global.myArray[e.id]);
Global.myArray[e.id]++;
trace("new onDataChange is called before function exits");
}
The function is called after data in array was changed and inside that function you changing the data again. Basically it's similar to doing something like this:
function f(x:Number) {
f(++x);
}
You can see what happens in such case if you toggle myArray.blockCircularChange. Sometimes you would intentionally want to have such recursion but it is likely that you will do it "by accident". Unfortunately flash will suddenly stop such events dispatching without even telling you why and this could be confusing.
Download full example here
Why using global variables is bad in most scenarios?
I guess there is many info about that all over the internet but to be complete I will add simple example.
Consider you have in your app some view where you display some text, or graphics, or most likely game content. Say you have chess game. Mayby you have separated logic and graphics in two classes but you want both to operate on the same pawns. So you create your Global.pawns variable and use that in both Grahpics and Logic class.
Everything is randy-dandy and works flawlessly. Now You come with the great idea - add option for user to play two matches at once or even more. All you have to do is to create another instance of your match... right?
Well you are doomed at this point because, every single instance of your class will use the same Global.pawns array. You not only have this variable global but also you have limited yourself to use only single instance of each class that use this variable :/
So before you use any global variables, just think twice if the thing you want to store in it is really global and universal across your entire app.

Resources