How do I make Message targets be the only recipent of a targeted Message? - silverlight-4.0

First time poster.
I'm using MVVM-Light with Silverlight 4 and RIA Services. This has been a learning experience! But so far, it's working beautifully. I was wondering two things. Right now, I'm using the Messenger framework to pass EntityObjects back to the ViewModel. For instance, I need to open a View Model with a specific "Course" object. So I instantiate the View, and the View sends a Message to the ViewModel with the Course. I've got a couple questions.
First question: Is this the best way to do this? I don't want to use Prism or Unity or any of those other things because I don't have the time to learn them. (This was, for me, the big draw of MVVM Light. The Light part.) But I couldn't see any other way to pass parameters to the VM Locator.
The second part is, this means I am sending messages from the View to that View's specific ViewModel. My messages look like this:
Tuple<Models.Course, Services.VWDS> courseDomainContextTuple = new Tuple<Models.Course, Services.VWDS>(Course, DomainContext);
NotificationMessage<Tuple<Models.Course, Services.VWDS>> message = new NotificationMessage<Tuple<Models.Course, Services.VWDS>>(this, this.DataContext, courseDomainContextTuple, Models.MessageString.EditCourse);
Messenger.Default.Send<NotificationMessage<Tuple<Models.Course, Services.VWDS>>>(message);
So, as you can see, I'm bundling the Course and the DomainContext (Ah RIA. Why won't you let me get the Context from the EntityObject?) and sending them to the ViewModel (which is "this.DataContext") - and yes, I know I should make a class for that message.
Here's the problem - every object that gets a Course and a DomainContext receives that message, not just the VM that I've designated the Target.
So, second question: Is that by design, or is that a bug, or am I doing something wrong?
Thanks!

To answer your second question, if you're sending a NotificationMessage of a specific type, anything registering for that same message type will receive the message. If you want to limit who receives the message, either create a new message class inheriting from MessageBase or NotificationMessage or whatever, send your message with a Token, or have an if statement in your message receive handler to filter out messages you don't care about.

Messaging is more useful when you need to communicate from one ViewModel to another, or you need to send a message where zero to many things can take action on it. From your View's code behind, I think you should just call your ViewModel directly. Its easy enough - here's how I usually do it in my code.
public partial class ExampleView : UserControl
{
private IExampleViewModel ViewModel
{
get { return this.DataContext as IExampleViewModel; }
}
public ExampleView()
{
InitializeComponent();
// Call directly to my View Model
ViewModel.SomeMethod();
// Register for View Model's event
ViewModel.SomeEvent += ViewModel_SomeEvent;
}
private void ViewModel_SomeEvent(object sender, EventArgs e)
{
// do stuff
}
}
I also included in the example how I handle communications from the ViewModel back to the View - through events.

Related

Access the EPartService after an RCP application has initialized

After my application initialized, I'm trying to automatically create a part within a part stack. I need the EPartService for this but I can't think of any way to properly get a hold of this service.
I've tried using the LifeCycle management to get the current IEclipseContext. However, whenever I try to access the service using the context, it's not found.
Any idea how I can do this?
You should be able to inject the EPartService in any of the defined methods in your life cycle class. However you won't be able to show a part until the application startup is complete. So use the App Startup Complete event, by adding a method like this to the life cycle class:
#Optional
#Inject
public void appStartupComplete(#UIEventTopic(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE) Event event,
EPartService partService)
{
....
}

The correct way to design data loading and object creation

I'm working on an app for iphone where I load a JSON from a php server, parse it with a library and create an object with this data. My code works fine but the way I do it seems wrong to me:
A viewController shows to the user a loading view. Meanwhile the ViewController makes the get request and receive the data.
The VC parse the response and get a dictionary
The dictionary is send to a "creator class" who returns a object created from the dictionary
I do two times this operation but I think it's a bad design:
Should a View Controller do a http request? Don't shoud be a "objectLoader"? The main method of creation class makes a big bunch of if/else spaghettis, like:
for(NSString key in dictionary){
if(key isEqualToString "a key"){
perform action
}
else if(key isEqualToString "an other key"){
perform action
}
....
}
Any idea to solve that? I was thinking about make a dictionary of keys/selectors to solve it and do something like:
for(NSString key in dictionary){
[self performSelector:[selectors getObjectForKey:key]]
}
But I don't know if I can reference a selector in a dictionary...
Finally the other option that comes to me is send the parsed dictionary to the object with a class method like: [ClassName createObjectWithDictionary:parsedDictionary]. That's a good way to do it?
I know the question is a little ambiguous but I'm a little lost in what Design patterns I should apply and who is responsible of what in this story
the best way is to use MVC pattern and have model with data that has methods to push and remove some data inside it and a list of delegates (derived from UIViewController) which are notified in case of changed model data.
Controller (not UIViewController) is something that initiates fetching data from server and handles results.
And all of UIViewControllers handles data changes and user interaction.
For now, write some RequestController (singletone or not, doesn't matter) that handles request routines and stores all necessary data to trigger events in controller.
You can use blocks or NSNotificationCenter to handle request's completion.
After getting necessary data through RequestController from request, your Controller can create necessary parsers and push parsed data into model.
Personally, I would NOT let the ViewController do the HTTP request. I always write service classes in my apps, that do the low level stuff and inform the caller (e.g. a view controller) via delegation on any received result.
So the control flow in that case is:
-> ViewController locks screen with loading message
-> calls service with itself as delegate - the service does the work and receives the answer -> the answer is processed and the result passed to the delegate
-> the ViewController takes the response, removes the loading message and does whatever is necessary with the response.
Concerning your second question: yes, it is possible to dynamically chose a selector out of a dictionary - e.g. by storing the selector's name in the dictionary and then use
SEL selector = selectorFromString(#"doWork");
to create the right selector to call.

Why does adding 2nd level subclassed Button controls to a Grid give E_INVALIDARG?

I've come across the this problem dealing with subclasses of the Windows.UI.Xaml.Button class in C++/CX, and I'd like to know what's going on.
If I add a control instance to a grid, everything works as expected.
If I subclass the control and add an instance of the subclass, everything works as expected.
But if I subclass my subclassed control and add an instance of it to the grid I get E_INVALIDARG thrown during Grid::Children::Append(). What gives?
My code looks roughly like this (LayoutRoot is a Grid in MainPage.xaml, this sample has been tested in an empty simple metro application):
// Scenario 1: This works (duh!)
LayoutRoot->Children->Append(ref new Button());
// Scenario 2: This works
LayoutRoot->Children->Append(ref new MyButton1());
// Scenario 3: This doesn't work, it will cause an E_INVALIDARG to be thrown by the collection
LayoutRoot->Children->Append(ref new MyButton2());
// This is how MyButton1 and MyButton2 is defined
public ref class MyButton1 : public Button {
public:
MyButton1() {};
~MyButton1() {};
};
public ref class MyButton2 : public MyButton1 {
public:
MyButton2() {};
~MyButton2() {};
};
Note that this question is slightly similar to this question, but the error and the scenario is sufficiently different for me to post this one separately.
UPDATE: I think I'm on the right track understanding this problem after reading this article by Ian Griffiths, but I need to know more regarding the behavior of this specific example. Full code to repeat this problem can be found here, see the 3rd post in the thread.
UPDATE: From what I've learned so far, not all WinRT types support inheritance. I have no reliable source references for this, but I've read that the Windows.UI.Xaml classes should support inheritance, but other WinRT types won't. The Windows.UI.Xaml.Controls.Button class obviously does, while my own MyButton1 doesn't. I'd like to know what I'd have to do to make MyButton1 'inheritable' the way the Button class is.
I've found that replacing the Windows.UI.Xaml.Controls.Button class with Windows.UI.Xaml.Controls.ProgressBar will make scenario 2 fail, which tells me that the ProgressBar class isn't (yet) possible to subclass. This observation is what makes me believe that a class need to do something explicit in order for it to be inheritable.

How can I use the FilterFunction passed to Gdk.Window.AddFilter?

I need to intercept several events before they are delivered to the widget's standard handlers, so I've done this already:
//Inside the definition of my custom widget
protected override void OnRealized()
{
base.OnRealized();
this.GdkWindow.AddFilter(PreFilterMessage);
...
}
So, later I define the PreFilterMessage method:
public Gdk.FilterReturn PreFilterMessage(IntPtr xEvent, Gdk.Event evnt)
{
Console.WriteLine(evnt.Type);
...
}
But the thing is that when I test it, whatever message gets to the window (KeyEvent, ButtonEvent, etc.) it always prints "Nothing", so I'm only getting empty events every time. Somewhere I read that the real information gets through the xEvent parameter, but that's just an IntPtr, so I don't know how to get the information I need (event type, pointer coordinates, etc.) from it.
Can anyone tell me how to do this? Thanks in advance.
Per the docs on the gtk.org website, the GdkEvent received in the filter func is unpopulated. The purpose of this AddFilter mechanism is to allow the user to intercept X events before the gdk event processing starts up. We do not bind any of the X data structures in Gtk#, so you would need to manually marshal that data from the IntPtr using System.Runtime.InteropServices Marshal.
So, unless that sounds familiar as far as what you are trying to accomplish, you may want to consider other alternatives.

Explain ASP.NET Events

See Also:
understanding events and event handlers in C#
As a web dev, I don't typically have to get into building my own events for objects, since most are inherent in the page. However, now I'm into a pretty complex (web) project where I think I may have to use them. I just read a chapter out of Pro VB 2008 and the .NET 3.5 Platform regarding events, delegates and lambdas (ch. 11) and while I have a better idea of what's going on, I am still having trouble wrapping my mind around when exactly to use them and how to use them. I understand their implementation, but the example in the book is a bit contrived.
I was hoping someone with a bit more understanding on the subject of events could provide me with a really solid example.
For my real-world application, I'm trying to use an event that would let me know when an item (some class, named OrderItem) has been updated and perform actions based on whether or not it's been updated. I considered using a flag/boolean property, but I know this doesn't smell right, and it's high-time I learn about how to use events correctly.
Thanks a lot!
EDIT Ok, so I guess to clarify a bit, what is the point of calling an event when all it is doing is calling a method? Why not simply call the method? This isn't a duplicate either, as I'm talking conceptually and she wants to know about handlers specifically. Also, I want to know what the difference would be between using an event or a "flag" property. And what do people mean by "subscribe" to an event?
Lets say you had an elevator system, and the part that moves up and down is called the ElevatorCar. When a person pushes a button to go to the 5th floor, it would make sense for the ElevatorController to call the ElevatorCar.RequestToFloor(5) method. Now when the car actually arrives at the 5th floor, it makes sense for it to raise an event like ArrivedAtFloor, passing 5 as the argument. The ElevatorController class would subscribe to the ArrivedAtFloor event of the ElevatorCar class.
This is all becauase the ElevatorCar class doesn't "know" anything about the ElevatorController class, but the ElevatorController class does know about the ElevatorCar class. Therefore the ElevatorCar class is given instructions by means of Methods, and it notifies the outside world of stuff that happens by means of events.
Does that make any sense?
EDIT:
Ok, first, go read the excellent answer listed in the See Also link (assume you've done that). An event is basically an object saying "if you want me to call you whenever X happens, then register your method here". Registering an event handler with the event is "subscribing". This allows encapsulation. So you can write, for instance, your ElevatorCar class once, and use it many times by many other classes.
As for the difference between using an event, or just calling a method, you have to ask yourself, should the ElevatorCar know about the ElevatorController class. If ElevatorController calls ElevatorCar.GoToFloor(x), how could the ElevatorCar class "call back" to ElevatorController without storing a reference to ElevatorController? That means the call has to become ElevatorCar.GoToFloor(int floor, ElevatorController ctrlr). Then the ElevatorCar class eventually has to call ctrlr.ArrivedAtFloor(floor). But you get into a lot of complexities... what if there's more than one car? You probably have to call ctrlr.ArrivedAtFloor(floor, this). Passing around references to yourself isn't optimal.
As for just setting a property, how does the other class know to come and read the property? The only way is to poll the property over and over to check for it to change. You can solve this, of course, by implementing INotifyPropertyChanged, but then again you're back to events!
Events are a specific case of the Inversion of Control (IoC) pattern. The traditional control flow, the caller invokes a method on the callee (like you are suggesting). With IoC (and thus events), we change around the application control and instead of tell the callee what to do, we tell the callee to notify us when something we are interested in happens.
Consider the case of a Timer. I want to be notified every 5 seconds (say). I don't want to constantly poll the timer ("is it time yet? is it time yet? is it time yet?"). Instead, I want to invert the flow control of my application. I want to tell the timer: "When it's time, please tell me by calling this method." That way, control is "inverted", the callee is invoking a method on the caller!
Consider the following code ...
using System;
using System.Timers;
namespace TestTimer
{
class Program
{
static void Main(string[] args)
{
// create my timer.
var t = new System.Timers.Timer(1000);
// register for notification
// tell the timer, "when it's time, call TimerGoesOff method"
t.Elapsed += new ElapsedEventHandler( TimerGoesOff );
// start the timer
t.Start();
// wait
Console.ReadLine();
}
// this gets called when the timer goes off
public static void TimerGoesOff(object source, ElapsedEventArgs e)
{
Console.WriteLine("The Time is " + e.SignalTime);
}
}
}
Rather than call a method on the Timer to ask when it will go off again (as you suggest), I tell it, "when you go off, call the TimerGoesOff" method. Now, instead of just waiting for the Timer to go off, I could do some work. Consider this code ...
using System;
using System.Threading;
using System.Timers;
namespace TestTimer
{
class Program
{
static void Main(string[] args)
{
// create my timer.
var t = new System.Timers.Timer(1000);
// register for notification
t.Elapsed += new ElapsedEventHandler( TimerGoesOff );
// start the timer
t.Start();
// do some work while timer is going
new Thread(() => DoWork()).Start();
Console.ReadLine();
}
// this gets called when the timer goes off
public static void TimerGoesOff(object source, ElapsedEventArgs e)
{
Console.WriteLine("The Time is " + e.SignalTime);
}
public static void DoWork()
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine( "Working ..." );
Thread.Sleep( 1000 );
}
}
}
}
Now, I get output something like ...
Working ...
The Time is 8/25/2009 1:05:59 PM
Working ...
Working ...
The Time is 8/25/2009 1:06:00 PM
Working ...
The Time is 8/25/2009 1:06:01 PM
Working ...
The Time is 8/25/2009 1:06:02 PM
The Time is 8/25/2009 1:06:03 PM
I have used the Timer.Elapsed Event to change the control flow of my application. I can go off and do work while "waiting" for the timer event to pulse. This is made possible by IoC and Events.
This is particularly visible (hehe) in User Interfaces. I don't want to keep asking "has the user done anything yet? has the user done anything yet?" (that's the way it used to be done way back when). Instead, I tell Controls for example, "when the user clicks you, let me know". That way, I can go off and do other great stuff and still be responsive to the user.