I am learning prism and I have hit a problem.
I have made an app very similar to the one that Mike Taulty makes in is great tutoral about Prism. The biggest difference is that my app is a WPF app instead of Silverlight.
I am finding that I have hit a problem though. When I close the main shell window, the app does not exit. The window goes a way, but the debugger is still active.
I have tried looking for call stacks and such, but Visual Studio just tells me that it is "External Code".
Any ideas on what I can do/look for to fix this?
Override the OnStartup method in the code behind of your App.xaml, and add this:
this.ShutdownMode = ShutdownMode.OnMainWindowClose;
HTH
The answer of Dyer solve only part of the problem.
I had the same issue, and after a while I found out that region navigation commands are not working well either.
The problem was with the Shell creating in Bootstrapper.
When I fixed that, I got 2 Shell windows instances.
Why?
The real problem was the startup Uri in the app.xaml.
You can't have both startup Uri with Shell creation in Bootstrapper.
Remove it from the app.xaml, fix your Shell and no need is this "Patch" and your app will behave as it should, it will close when you close the Shell.
Again, this is only a symptom, other issues will rise if you don't fix the Shell creation.
protected override DependencyObject CreateShell()
{
return this.Container.Resolve<Shell>();
}
protected override void InitializeShell()
{
base.InitializeShell();
Application.Current.MainWindow = (Shell)this.Shell;
Application.Current.MainWindow.Show();
IRegionManager regionManager = this.Container.Resolve<IRegionManager>();
regionManager.RegisterViewWithRegion(RegionNames.MainRegion, typeof(MainView));
}
Related
I have an existing WPF project and I want to move it over to caliburn with MEF.
My shell is a viewmodel called MainViewModel this opens up a dialog using the DefaultWindowManager this is a login window this all works fine but after logging in the program stalls for a little bit then exits. and the MainView never becomes visible. With debugging I checked and verified that the MainView does get created it just never becomes active or visible.
I tried inheriting my MainViewModel from Screen, IShell and NotifyPropertyBase, IShell and IShell. Does anyone have any ideas or clues for me to try thanks.
I am not using caliburn in the MainView and ViewModel besides for the view to view model linking as I just took the old view/view models could this have to do with anything? Is there a way to turn of the ViewModelBinder for certain viewmodels/views?
I'll mention this in case your issue is the same as I had, as it slowed me down somewhat recently... If your Shell has some Imports that are not being satisfied then the Shell won't appear, and the effect is rather confusing.
Ensure that you have [Import(AllowDefault=True)] as your Attribute or use [ImportMany]
However, since you do say that in debugging there is an instance, the issue might be in the way you are using Caliburn(Micro?). In this case, I suggest you copy a Caliburn example and then add your functionality - least then you'll know it once worked.
Rgds
John
Actually Rob Eisenberg of caliburn was very helpful and he helped me out with this issue.
The problem was that when I switched to caliburn the LoginView was the first window to be opened and it was closed before the MainView window was opened.
windows treats the first window opened as the mainwindow. and when the mainwindow is closed windows checks if other windows are open if not it closes the application.
He provided a possible solution of making the loginviewmodel the shell and closing it after opening the mainviewmodel.
I am trying to make a system tray application that loads on startup and pops a balloon text every 2 hours. If there is such an example its great.
I am looking to use.
WPF,
Timers,
Delegates, events
I am not sure if these are enough or do I need something more.
Thanks in advance.
I think you will be fine with those. All you need is actually a NotifyIcon and a Timer. I've accomplished similar this way, except I wasn't using WPF (I rather used the 'classical' Window designer).
The simplest way to let your app start on startup would probably be to put it into Startup folder in the Start menu, there's actually no need to use the registry.
First of all here is what you need about starting your application on system startup :
Lets say I have a checkBox and I want to start my application on windows startup if this checkBox is activated :
RegistryKey rkApp = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
private void checkBox_autoStart_Checked(object sender, RoutedEventArgs e)
{
rkApp.SetValue("Your Application Name Here",Assembly.GetExecutingAssembly().Location);
}
and about the deactivation of that you do the follwoing :
private void checkBox_autoStart_Unchecked(object sender, RoutedEventArgs e)
{
rkApp.DeleteValue("Your Application Name Here", false);
}
p.s : Your application name will appear on the task manager the way you write it up there
And about using a notify Icon , well actually WPF doesn't support a ready made one so either you use the Windows Forms Notify Icon or you use the one mentioned in a nother answer from codeproject.com
if you wanted to use the one that already exists in windows forms , you have to add a reference to System.Windows.Forms in your project
A windows service may be the best thing for running in the background, but it may be tricky to get access to the GUI from a service (I don't think it's trivial).
For a WPF desktop app to do a tray notification, see this project with demo and source code: http://www.codeproject.com/KB/WPF/WPF_xaml_taskbar_window.aspx
To get the notification every 2 hours, you can use a DispatcherTimer:
http://social.msdn.microsoft.com/Forums/en/wpf/thread/aaffea95-e735-492d-bd8a-2fdf7099a936
I have developed a simple DB-editing app using Xceed's excellent DataGrid for WPF (UX Edition version 3.7), which is now ready for deployment... except that when I run it on a machine other than the development one where it was built, I am getting the runtime exception for invalid licensing.
I have included my license key in the App.xaml.cs exactly as specified in the Xceed docs, like so:
public partial class App : System.Windows.Application
{
protected override void OnStartup(StartupEventArgs e)
{
Xceed.Wpf.DataGrid.Licenser.LicenseKey = "DGF37-xxxxx-xxxxx-xxxx";
base.OnStartup(e);
}
}
The correct version of the DataGrid DLLs are being included in the setup and the application's program directory, and there are no other versions on the target machine.
Debugging doesn't show me anything useful other than the LicenseException that is thrown when the code tries to use the DataGrid, with the message that reads "Xceed.Wpf.DataGrid.Licenser.LicenseKey property must be set to a valid license key in the code of your application before using this product..."
Any idea what's going wrong here?
Oh, poop... figured it out, and it was a stupid mistake. My OnStartup event was misplaced, outside of the app's namespace.
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.