Starting a WPF application as hidden - wpf

I'm writing a WPF application and want it to start as a hidden window. I've created the Window object and set its Visibility property to Visibility.Hidden before calling Application.Run(). Then, I have an event handler for Window.Loaded that also sets the visibility to Visibility.Hidden. Between the call to Application.Run() and the callback to OnWindowLoaded(), there is a black outline of the window that flashes up on the screen and then disappears. It's like the window manager is creating a drop shadow for the window or something and then hides it immediately.
After running my project through instrumentation, I finally found that Window.Show() was somehow getting called. So, I looked into the source code at http://www.dotnetframework.org/Search.aspx:
Application.Run() ends up calling a private method named Application.RunInternal().
RunInternal() checks the visibility of the Window object that was passed in to the Run() method.
If the Visibility property is not Visibility.Visible, a call to Window.Show() is made.
I then looked at the source for System.Windows.Window:
Window.Show() sets the Visibility property on itself (the window) to be Visibility.Visible.
Based on this, I don't see how to force the window to stay hidden. By trying to make the window invisible at startup, I'm causing the Application object to call Window.Show(); I don't understand why the Application object even cares about the window's visibility. It's been a frustrating experience... :-(
I've seen other answers that say to not call Application.Run() and to instead set up your own event dispatchers, but that seems like overkill for something that should be easy. I just want the main window to stay hidden, for no "flicker" to appear at app startup, and for the window to become visible when I'm ready for it to do so (which happens later in my application logic).
Can anyone offer a suggestion?

Did you remove the StartupUri entry in App.xaml? If you do, the App class won't instantiate the window for you and show it. You can do this by yourself by overwriting the App.OnStartup method.
Basically, I build a composition root in this OnStartup method and just create a window at the end of the process:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
// Do your custom initialization code here
MainWindow = new MainWindow();
MainWindow.Show();
}
If you really want to omit the whole application build up process (which I wouldn't recommend, as you won't have features like the fallback to Application Resources), you can create a Dispatcher by yourself using this code:
var dispatcher = Dispatcher.CurrentDispatcher;
var synchronizationContext = new DispatcherSynchronizationContext(dispatcher);
SynchronizationContext.SetSynchronizationContext(synchronizationContext);
Dispatcher.Run();

The comment on this Answer finally led me to find the solution to this issue. I needed to display multiple windows on multiple screens at once, and by minimizing the window it gives me the performance I needed. Thanks.

Related

Intercept Deactivation Strategy of a Closing window?

I'm using the latest version of Caliburn Micro (4.0.173) in an application leveraging IoC.
I do not have a sample project yet has my sandbox is using nugets from Telerik that are not easily findable. But I think a detailed explanation can get the point across:
I have a ProfileEditorViewModel : Conductor<IScreen>.Collection.OneActive resolved by the container (singleton) through the constructor of my ShellViewModel and I use the I use the WindowsManager to open my ProfileEditorViewModel in a different window:
public class ShellViewModel : IShellViewModel{
private readonly IProfileEditorViewModel _profileEditor;
private readonly IWindowManager _windowManager;
public ShellViewModel(IWindowManager windowManager, IProfileEditorViewModel profileEditor){
_windowManager = windowManager;
_profileEditor = profileEditor;
}
//Method triggered by an Action from the View
public void OpenProfileEditor(){
_windowManager.ShowWindowAsync(_profileEditor, null, null);
}
}
When I close the ProfileEditor window (clicking on the top right red cross), it triggers a closing type deactivation, which is coherent with the implementation of a conductor (not being conducted itself) being shutdown. The Screens collection is being wiped and some more cleaning is being done through the Screen.cs implementation of Caliburn.
However, for this application, I'm facing "the view not being unbound" issue (https://github.com/Caliburn-Micro/Caliburn.Micro/issues/361) and next time I open the ProfileEditor, it'll bind a new view (because the Views Collection of my viewmodel was empty) and it create some issue related to UI components used in the view (basically one event from the viewmodel triggers similar actions, on the view(s) side, that all come back to the viewmodel, which create some identification issue)
Reading through the issue 361, I'm currently able to catch the Unloaded event of my ProfileEditor (once closed), and basically clean the DataContext of any view associated to the viewmodel (before Screen cleans the Screens collections). Next time I open the ProfileEditor, it'll bind a new view and it'll be the only one = it works.
However clearing the DataContext may produce some other issue down the road.
What I would like to do, is to avoid clearing the View collection of the ProfileEditorViewModel upon closing. So Caliburn can use this reference the next time it needs to resolve a window/view for the ProfileEditorViewModel (instead of looking for a new one).
Is it possible to intercept the Deactivation / Closing strategy and change the close parameter to false ?
Another solution may be for my ShellView to be a Conductor<>.Collection.AllActive but I can't wrap my head around teh management of a window closing. How to intercept the ProfileEditor windows closing and proceeding with a deactivation of the ProfileEditorViewModel instead of a closing.
I hope it make sense :)
Thank you in advance for your help

Dialog Window for configuration in MVVM

i'm relative new to MVVM. My current problem is a modular dialog which should "autostart" at the beginning.
I've followed the example of WAFs Email Client for modular dialogs. Is it right that the only important thing is to set the Owner Property of the dialog to the instance of the main window of the application (and of course show the window with ShowDialog() instead of Show()?
If you close this dialog without configuration the application will shutdown. But now, if I open the main window in visual studios designer mode the configuration dialog comes up and if I close it visual studio crashes.
This is because I call the ShowDialog() of the configuration dialog in the constructor of my main windows view model.
To avoid this i can check for DesignerProperties.IsInDesignTool Property, but this is more a workaround as good code style, right?
Do you have any suggestions? Thanks.
The problem here is that you are showing a dialog in the constructor of a class. That's something you don't want to do.
I would solve it like this:
Don't specify a StartupUri in your app.xaml but override OnStartup. There you check whether the configuration dialog should be shown or not. If it should be shown, show it and after it has closed with OK, show you main window.
Something like this:
override void OnStartup(...)
{
if(configurationNotComplete)
{
ConfigDialog cfg = new ConfigDialog();
if(!(cfg.ShowDialog() ?? false))
{
Shutdown();
return;
}
}
MainWindow window = new MainWindow();
window.Show();
}
You have another problem with your current approach: Your ViewModel shows a modal dialog. This means it knows at least about one View: That of the modal dialog. MVVM is one way: The View knows about the ViewModel, the ViewModel knows about the Model. There should be no connection in the other direction.

The whole wpf application is blocked after i call Show() for new window

I am developing a WPF-application using mvvm pattern. And a strange problem occurred to me.
There is a form, which contains a devexpress DXGrid control. There is a command binded to double click gesture in presenter. When the command triggers a new window is created and shown through factory class(the Show() method is used).
So, it happens from time to time that the whole application(all application windows) is blocked when this window is shown. This lockup disappears after i focus any other application.
For the first time this problem occurred after updating devexpress version. Then this problem occurred any time new window was shown after double click on grid row. The problem was partially fixed by setting new window`s Owner property.
Now this problem occurs from time to time. It seems as if threads are involved here, but i dont understand how. =(
p.s.:
there is one more strange thing, when new window is shown and no lockup-problem occurred, the first window is still focused and i have to click on newly shown window before i can use any controls, placed on it.
I have tried:
set ShowActivated property
call Activate() after Show()
newform.Dispatcher.CheckAccess() to
determine which thread calls Show()
method
check newform.IsActive property after
show (value = true)
Could you tell me how to fix, please?
Thank you.
Well to fix the issue of first window being focused rather than the newly shown window, you need to do the following, after calling the show method for the new window:
Mouse.Capture(null);
Hopefully the issue would be resolved.

General Question About WPF Control Behavior and using Invoke

I have been putting off activity on SO because my current reputation is "1337". :)
This is a question of "why" and not "how". By default, it seems that WPF does not set focus to the first control in a window when it's opening. In addition, when a textbox gets focus, by default it does not have it's existing text selected. So basically when I open a window, I want focus on the first control of the window, and if that control is a textbox, I want it's existing text (if any) to be selected.
I found some tips online to accomplish each of these behaviors, and combined them. The code below, which I placed in the constructor of my window, is what I came up with:
Loaded += (sender, e) =>
{
MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
var textBox = FocusManager.GetFocusedElement(this) as TextBox;
if (textBox != null)
{
Action select = textBox.SelectAll;
//for some reason this doesn't work without using invoke.
Dispatcher.Invoke(DispatcherPriority.Loaded, select);
}
};
So, my question. Why does the above not work without using Dispatcher.Invoke? Is something built into the behavior of the window (or textbox) cause the selected text to be de-selected post-loading?
Maybe related, maybe not--another example of where I had to use Dispatcher.Invoke to control the behavior of a form:
WPF Focus In Tab Control Content When New Tab is Created
All WPF controls have thread affinity. The Dispatcher manages the thread that each control was created on (typically this is a single thread for every control in the application, but not necessarily). Work is queued on this thread and executed in priority order.
Any UI-manipulating code has to be executed on the same thread as the control was created on - the Dispatcher thread - and so any method has to invoke back to that thread before it can do anything that would affect the UI (such as selecting text in the TextBox).
That said, it's my understanding that the Loaded eventhandler would fire on the Dispatcher thread by default, so I'm not entirely sure why you're seeing this behaviour in your specific example!
I should start by mentioning i had no issues making that work w/ out the dispatcher call in .net 4.0 (it may have been fixed in the framework update)- however, what the previous poster mentioned is accurate and has been the pardigm since the dawn of winforms (.DoActions() and .Invoke()). However, in 3.5 the above did work w/ out dispatcher if you use a method defined in the codebehind as the target call in your lambda:
Loaded += (sender, e) =>
{
this.SelectText();
};
void SelectText()
{
MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
var textBox = FocusManager.GetFocusedElement(this) as TextBox;
if (textBox != null)
{
textBox.SelectAll();
}
}
As to why, I cant really give you the specifics but I've run into similar issues w/ using lambdas to route events on presenters. I want to say its something to do w/ reference or context of the compiled expression- in this case it needs a ref to the containing object in order to know how to delegate the operation (selecting the textbox text on the right thread). I also believe that GC can occasionally clean up resources so deferred execution gets botched (seen it in F#...believed that was the cause of my issue in C# as well).

WPF Startup Screen like Blend

Our main WPF window ('Main Window') takes considerable time to create (it is using a ribbon and docking panel similar to Visual Studio). Just like in Blend the first action will always be to either choose an existing project to work on or to create a new project. Therefore we would like to show this 'Select Project' window as quickly as possible and create the heavy 'Main Window' in the background (invisible until the user clicks OK on the 'Select Project' window).
What's the best way to architect this startup scenario, preferably using 2 WPF windows (one for the project selection and one for the main control)?
I'm aware of this sample which demonstrates how to load a Win32 window shortly after application startup, but I'd prefer a WPF-only solution.
Another potential solution is to use multiple WPF UI threads, however lifetime management and window-to-window communication are non-trivial.
Questions:
Will I be able to see a faster startup time when implementing the 2 WPF window solution as compared to simply creating the 'Main Window' and not implement the 'Select Project' window (assuming I can find an implementation that takes care of the window lifetimes)?
Should the 'Select Project' window be created on the main application thread and the 'Main Window' on a background thread (or visa versa)?
If I need to use a Win32 startup window for speed, how would I communicate the user's choice of project name to the main WPF application window?
Does anyone know how Blend actually implements their startup window (which I am trying to mimic here)?
Any implementation pointers would be much appreciated!
Best way to architect this scenario
I would:
Create classes to manage the data for your "Select Project" window (such as MRU lists, templates, etc), making sure they are self-contained and don't require interaction with the main thread.
Store information about the "current" project(s) in the Application object or a singleton object.
Create the "Select Project" window to operate completely independently of the main window.
Set your "Select Project" window's "Open" and "Create" buttons to fire the Application.Open command, and bind the CommandParameter on the button to the property that contains the filename to open (or the template to instantiate).
Add a CommandBinding for the Application.Open command at the window level to take the command parameter and set the current project in the Application object.
In your application's startup code, immediately spawn a thread to create the "Select Project" window, then immediately do {a Dispatcher.Invoke at ApplicationIdle priority followed by a very short Thread.Sleep} several times, then proceed, allowing the main window to be created but make it initially invisible.
Set a trigger in the main window to make it visible once the current project has been set for the first time.
Here is how the Open command handler in the "Select Project" window might update the project path in the Application object:
Application.Current.Dispatcher.Invoke(DispatcherPriority.Send, new Action(() =>
{
((App)Application.Current).CurrentProjectPath = e.Parameter;
}
Here is what the application's startup code would look like:
public override void OnStartup(StartupEventArgs e)
{
new Thread(() => { new SelectProject().Show(); }).Start();
for(int i=0; i<10; i++)
{
Dispatcher.Invoke(DispatcherPriority.ApplicationIdle, () => {});
Thread.Sleep(20);
}
_guts = new MainWindowContent(); // probably a UserControl
_guts.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
_guts.Arrange(new Rect(0, 0, guts.DesiredSize.Width, guts.DesiredSize.Height));
_guts.SetBinding(VisibilityProperty,
new Binding { Source = this, Path="StartupFinished",
Converter = BoolToVisibiltyConverter.Instance });
_mainWindow = new MainWindow { Content = guts };
// Note: Title and other properties of MainWindow would be set in the XAML
}
Note the extra code to make sure the guts get measured and arranged ahead of time.
Here is the code to set the current project path:
public string CurrentProjectPath
{
get { return _currentProjectPath; }
set
{
_currentProjectPath = value;
LoadProject();
_startupFinished = true;
OnPropertyChanged("StartupFinished");
}
}
This code assumes the XAML binds _mainWindow's Visibility property
StartupFinished is a DependencyProperty that the main window's Visibility property is bound to, but it could be done in other ways.
Will you be able to see faster startup time this way?
Yes.
Should Select Project be created on main thread & main on other thread, or vice versa
You should create MainWindow on the main thread so it shares the same Dispatcher with the Application object. That means "Select Project" has to be in the second thread.
If you need to use a Win32 startup window for speed
It is probably probably not necessary. Startup of WPF itself is only a fraction of a second. But if it is necessary, the Application.Current.Dispatcher.Invoke technique described above will work.
Do you know how Blend implements its startup window?
No
Do you have a full working axample that I might look at? I tried to work something up from the code snippets enclosed above but wasn't able to get an example to work...

Resources