I am relatively new to WPF, and some things with it are quite foreign to me. For one, unlike Windows Forms, the WPF control hierarchy does not support IDisposable. In Windows Forms, if a user control used any managed resources, it was very easy to clean up the resources by overriding the Dispose method that every control implemented.
In WPF, the story is not that simple. I have searched for this for several hours, and encountered two basic themes:
The first theme is Microsoft clearly stating that WPF does not implement IDisposable because the WPF controls have no unmanaged resources. While that may be true, they seem to have completely missed the fact that user extensions to their WPF class hierarchy may indeed use managed resources (directly or indirectly through a model). By not implementing IDisposable, Microsoft has effectively removed the only guaranteed mechanism by which unmanaged resources used by a custom WPF control or window can be cleaned up.
Second, I found a few references to Dispatcher.ShutdownStarted. I have tried to use the ShutdownStarted event, but it does not seem to fire for every control. I have a bunch of WPF UserControl's that I have implemented a handler for ShutdownStarted, and it never gets called. I am not sure if it only works for Windows, or perhaps the WPF App class. However it is not properly firing, and I am leaking open PerformanceCounter objects every time the app closes.
Is there a better alternative to cleaning up unmanaged resources than the Dispatcher.ShutdownStarted event? Is there some trick to implementing IDisposable such that Dispose will be called? I would much prefer to avoid using a finalizer if at all possible.
I'm afraid that Dispatcher.ShutdownStarted really does seem to be the only mechanism WPF provides for disposing of resources in UserControls. (See a very similar question I asked a while ago).
Another way to approach the problem is to move all of your disposable resources (if at all possible) out of the code behind and into separate classes (such as the ViewModel when using the MVVM pattern). Then at a higher level you could handle your main window closing and notify all the ViewModels via a Messenger class.
I am surprised you don't get the Dispatcher.ShutdownStarted event. Are your UserControls attached to the top-level window at the time?
The IDisposable interface has (almost) no meaning under WPF, because the mechanism is different from Winforms. In WPF, you must bear in mind the visual and logical tree: that's fundamental.So, any visual object generally lives as child of some other object. The base of the WPF building mechanism is to attach the visual object hierarchically, then detach and destroy when they aren't useful.
I think you may check the OnVisualParentChanged method exposed since the UIElement: this method is called either when a visual object is attached and when is detached. That could be the right place to dispose the unmanaged objects (sockets, files, etc).
I was looking for this too and after testing differents options I implemented the solution of venezia
protected override void OnVisualParentChanged(DependencyObject oldParent)
{
if (oldParent != null)
{
MyOwnDisposeMethod(); //Release all resources here
}
base.OnVisualParentChanged(oldParent);
}
I realized that when parent call Children.Clear() Method and had already items added to Children, DependencyObject had a value. But when parent added an item (Children.Add(CustomControl)) and children was empty DependencyObject was null.
While others have given you really useful information about this problem, there is a little bit of information that you may not have that will explain a lot about why there is no IDisposable. Basically, WPF (and Silverlight) makes heavy use of WeakReferences - this allows you to reference an object which the GC can still collect.
I've got this difficult when I'd used some connection to the database, using some IDbConnection implementation driver or Entity Framework.
I've found in these cases the recommendation is to keep one object connection/context per window, to be able to track changes/transactions. (link)
So I've overridden the OnClosing:
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
base.OnClosing(e);
this._context.Dispose();
}
The context can be my ViewModel/Control which implements IDisposable to clean resources.
Sample use of OnClosing to dispose of resources (link)
Related
I am developing a little utility view that will be embedded in several of our apps. It will sit in a common library.
Should I expose this as a ViewModel along with a default View implementation, or would it be better as a UserControl with a fixed GUI?
It is pretty self contained and I doubt it will need to be reskinned, but doing it as a UserControl seems a bit overkill with having to set up a load of dependency properties.
A simple ViewModel seems more attractive to me but wondered if this was the normal way of sharing stuff?
EDIT:
It would also be nice if I could embed this in WinForms apps too. Is this possible with View/ViewModel?
Well, in the end I went with View/ViewModel. This keeps the separation nicely and is easily pluggable into existing MVVM projects.
It also works fine in WinForms, given that a View is just a UserControl with its DataContext set to some arbitrary object (the ViewModel).
The only slight issue I had was the fact that Application.Current is not set in a forms environment, so I had to store the GUI dispatcher reference so I could marshal gui updates to the proper thread in my ViewModel.
I have been developing a Lync Silverlight application in Silverlight and now I am trying to shift it to WPF.
However, I am facing some thread affinity issues. For example I display the Lync client's state on my page in a textblock, and so in my code behind have wired a state changed event handler, that writes the new state into the textblock whenever the state of Lync client changes.
Now, this worked perfectly in silverlight but seemingly is not allowed in WPF.
Now my questions are:
How come it works in Silverlight bt not in WPF, even though Silverlight is supposed to be a subset of WPF?
Thread affinity is an important concept and I know we can use invoke dispatcher, but doesn't it just beat the concept of asynchronous programming in form of event handlers and callbacks?
I have a button defined in my XAML page, and the click event handler defined on it can access other UI elements, it does not suffer the problem outlined above.
But if I define a LyncClient instance in my code-behind, event handlers defined on it cannot access the UI elements. Why so, I detected no such difference between UIElements and other objects in Silverlight?
Based on above comments, I'll suggest the following "answer"...
I would guess it is more likely than not that there is some sort of different in the way that the SL API was written than that of the WPF api. That could explain the difference in the thread that is used when the API issues the callback. To verify this, you could:
Ask MS directly
Put some diagnostics code in your callback method to log the thread ID and compare that to the main thread of the application. Do this for both SL and WPF to see if they are the same or different threads.
Open the assemblies in Reflector to inspect how each API was written.
In terms of handling this specific situation, in your callback, you could:
Get the dispatcher object (different for SL than WPF) and always issue UI updates through Dispatcher.Invoke.
Use databinding and INotifyPropertyChanged to insulate the UI from the property. You could delcare a property on a ViewModel or in the code behind. Then bind the UI's textbox to that property. Databinding has some smarts in it that will automatically marshal property changes to the correct thread (in most cases anyway).
Hope that helps.
I'm using EntityFramework for data access and wpf as UI. If I bind WPF components to navigation properties of my entity classes(usually EntityCollection<EntityClass>, exposed as IList<T> in service layer), UI is not updating the changes. I know i have to use ObservableCollection<T> or such, but I need some guidance on how to use it without iterating back and forth upon save and retrieval processes.
(As you guessed, I'm new to WPF; so target your answers for a WPF beginner)
You don't have to use ObservableCollection. WPF actually depends upon INotifyCollectionChanged, which ObservableCollection implements. So if you create a wrapper collection which implements this interface and forwards the operations onto the EntityCollection and raises the events, you should be good (as long as you modify the collection via the wrapper and not the underlying collection. A similar concept is used for read-only collections (wrap an existing collection and interact with wrapper), simple Decorator pattern.
You can't use it directly (and have the changes be reflected).
Here is a link that explains how someone else solved this problem
I faced the same problem in Silverlight LOB applications
I've created a silverlight library called ObservableCollections accompanied with visual studio 2012 addin and NUGet support, to generate the boilerplate code in order to wrap the EntityCollection with ObservableEntityCollection class, I know your question is about WPF but it could help.
http://observableec.codeplex.com/
I am trying to find out if an EXE is a WPF app or a WinForms app. Any suggestions on how I can go about this?
I have heard that I could use the Reflector tool, if so how would this be done?
Thanks.
Although generally an application can be classed as 'either' a WPF or WinForms application, interoperability is possible such that a WinForms app can 'host' WPF controls and vice-versa. Since your application sounds like it references both sets of assemblies, it could be using both. Just something to be aware of.
Anyway, I've just opened one of my WPF projects in Reflector and some obvious indications it's a WPF application are:
1) There is an App class that has a StartupUri which is a Xaml file (like this)
public class App : System.Windows.Application
{
// Methods
[DebuggerNonUserCode]
public void InitializeComponent()
{
base.StartupUri = new Uri("Window1.xaml", UriKind.Relative);
}
2) There is a XamlGeneratedNamespace in the EXE
3) In the Resources 'folder' there are .baml files (probably within <Application1>.g.resources).
4) The window classes (if you can find them easily in the Reflector tree) implement:
public class Window1 : System.Windows.Window
, System.Windows.Markup.IComponentConnector {
If you really want to trawl through Reflector in detail, WinForms windows will inherit from System.Windows.Forms.Form so you can easily spot if you have both WinForms and WPF in there.
You can check the .exe with code, you do not need Reflector.
Simply find a type in the .exe assembly which inherits from the System.Windows.Application class which is from the PresentationFramework dll (you can do it with reflection).
Now, this isn't a 100% sure method, since theoretically someone could be creating a class which inherits from the wpf Application class, and then not start the app. The definite way is to check in Reflector if that class' Run() method is called.
And the programmatic way to check if the current application in which your code is running is a wpf app is like this:
public static bool IsWpfApplication
{
get { return System.Windows.Application.Current != null; }
}
Open it with reflector and see whether it references one of the PresentationFramework DLLs (then it's likely WPF) or System.Windows.Forms.dll. Note that applications might reference both - in that case, you can't really tell.
Maybe it's easier just from looking at the application. WPF applications are rendered smoother, even with standard controls.
Generally one dead give away is that WPF applications tend to have a different looking focus rectangle on focused items such as buttons or listboxes. The standard Windows focus rectangle is 1px wide and on WPF apps it seems to just look... different.
Also, WPF apps render most elements to memory bitmaps whenever they need to perform some kind of animation and this results in a "fuzzy", almost anitaliased look whenever the particular animation takes place and is displayed onscreen. This effect is noticed in things like, menu highlights, scrolling or general button text after you click.
Im building a wpf app with the composite application block ("prism") V2, and Im having an issue where a user control that is injected by a module is very slow in rendering. The user control contains a datagrid with some 2000 rows in it and there is considerable lag in the control rendering to the screen. Initially I thought the slowness was due to the wpf toolkit datagrid control itself but this is not the case. When I move the control containing the datagrid (TestControl) out of the external module and into the shell project and load it straight from there the control renders immediately without any problems.
Im using the following code in the implementation of IModule in my module to inject the wpf user control into the shell
this.regionManager.RegisterViewWithRegion("mainRegion", typeof(TestControl));
Is there performance issues when loading controls from other modules in a prism app? Whats the most optimal way to load them in?
Thanks
the problem here seemed to be wpf being slow to update when the UI is being updated vai the dispatcher from a background thread. I took up the conversation on codeplex and got it more or less sorted.
http://compositewpf.codeplex.com/Thread/View.aspx?ThreadId=64113
It's likely this is an artifact of the lifecycle events. Your shell is going to display well before your modules start to load and register themselves. If you do this it will "appear" to take longer because your UI will appear with a big fat hole in it until the module initialization code fires.
A lot of the samples have you doing something like "Shell.Show();" in your CreateShell method of your bootstrapper, but you might consider moving the references to the Shell to a private member of your bootstrapper class and calling .Show() on it in, like this:
public class Bootstrapper : UnityBootstrapper
{
Shell shell;
protected override DependencyObject CreateShell()
{
shell = Container.Resolve<Shell>();
return shell;
}
protected override void InitializeModules()
{
base.InitializeModules();
shell.Show();
}
I tried this just now and it definitely felt like my app got a performance boost, so I think I'll make this change myself.
If your modules take a really long time to load, you also might want to show a splash screen between CreateShell and after InitializeModules.