I am writing an app using the MVVM (Model-View-ViewModel) pattern and am leveraging the Prism and Unity bits from the Microsoft P&P team.
I have a View with a list of items. These items are contained with an ObservableCollection in the ViewModel to which a listbox in the View is databound (the ViewModel is set as the DataContext of the View). In the ViewModel, I have a timer running that fires a poll of the server for new data every 30 seconds. When the data returns开发者_Go百科 I marshal it over to the UI thread and add the new data to the ObservableCollection. This all works really well.
The problem I have is that I need the timer to stop when the view is closed. I am not sure what event to watch for here. Is there something in Unity that will tell me when the view has been replaced in the region? Is there an event which would be best to use for this from the view, and perhaps pass that event (or a facade) on to the ModelView? My View is a UserControl per P&P examples. There is no "Unload" event I could find nor a method to override.
I am already thinking of writing my own service to handle view changes (some sort of facade for the RegionManager), and might just implement a common interface on my Views to do cleanup or implement IDisposable on them when they are removed from a view. However, if there is a clean way of doing this with the confines of the core Silverlight framework or Unity/Prism, I would prefer to take that path.
Edit - Answer:
I ended up marking Anderson Imes's answer simply by picking the one that was closest to what I am doing for my solution. But really, I am using parts from from PL and GraemeF as well and up-voted everyone. This was a great response for me, as it gave me some better insight into the regions, gave me another framework to look at, and verified that I was probably going down the right path with implementing a service to handle view changes instead of just calling into RegionManager.
I think what you are looking for is IActiveAware interface from Region Manager framework (see RegionActiveAwareBehavior):
The RegionActiveAwareBehavior is responsible for notifying a view if it is active or inactive. The view must implement IActiveAware to receive these change notifications. This active aware notification is one-way to the view; the view cannot affect its active state by changing the active property on the IActiveAware interface.
Caliburn addresses this missing piece of Prism with its IPresenter Component Model and works well with Prism. You would implement the IPresenter
interface (or more likely use one of the base classes) on your ViewModels, and stop the timer in OnShutdown
and/or OnDeactivate
.
You could either use Caliburn yourself, or have a look and see how it is implemented.
I had this exact problem and ended up basically creating an interface for this:
public IApplicationEvents
{
void OnClose();
}
I centralized my close view code and basically just looked for this interface before removing the view. If it was there, I could call it (I checked both the View itself and also the DataContext property if it was a UIElement).
I gussied it up a little using an attached property and the EventAggregator, but this is the basic idea and it works well.
You are right to need to shut this down when you view closes, especially if you are using DispatcherTimer (as you should). This thing causes some really bad memory leaks if you don't.
精彩评论