I have Two WPF window Window1.xaml and window2.xaml.
In window2.xaml.cs i have one function which does some complex calculation and display intermediate resuls on a TextBlock.
Now What i want.
by clicking on button of Window1.xaml i want to open Window2.xaml as a dialog box and want to execute complex function of windows2.xaml.
If i call complex button on Window2.xaml' load event then dilog box apear after execution of complex function.
How to do this by Threading.
You need not open the window in a thread. Once you've opened Window2, start a thread for the complex function in the Window2.Loaded event handler. This will leave your UI undisturbed.
Opening a Window in a thread that is not UI thread is not recommended at all. You can open a popup window using Show() (modeless) method or ShowDialog() (modal) method. In Window2's load method, you can start a new thread which does a complex operation and once it is done with the operation, it can show a dialog.
Now, while in a different thread than UI thread, if you want to show any UI (dialogs, windows) or change existing UI (textblock, etc), you must use Dispatcher.Invoke method.
Related
I have a WPF application using Prism framework. It has three regions that gets loaded in shell. Now, I have a requirement for which have to display a dialog once the main window(all the regions) is loaded. i.e. dialog should display on top of main window. I tried to publish an event during shell initialization,however dialog display only when I close main window or if publish the event in one of region's usercontrol constructor, it displays the dialog first and when dialog is closed main window loads. Now, am thinking if there is any way I can find if all the regions are loaded through an event then I can publish the event there.
Questions:
1. Is there any event that I can use to detect if all the regions are loaded?
2. Is there any other approach that you can point me to to achieve this requirement?
Put this in the constructor of the parent control
Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() => {code that should be executed after all children are loaded} ));
Is there any event that I can use to detect if all the regions are loaded?
Override PrismApplicationBase.OnInitialized and call the IDialogService from there.
I bind DelegateCommands to buttons in the UI.
And I am not using Prism.
Now I want to disable/hide certain controls on the UI when a button is clicked.
Do I have to put the Disable/Hide logic into the execute handler of the DelegateCommand itself?
Special focus here: background Worker thread.
this.MyCommand = new DelegateCommand(MyExecutehandler);
void MyExecutehandler(object obj){
// 1.) disable controls here
// 2.) long running operation on background worker here
// 3.) enable the controls again in the worker_completed handler?
}
The controls would then be disabled/enabled through MVVM.
Special focus here: background Worker thread
So i just make an assumption that you are asking how to modify UI control state from another thread.
Normally we use way below to modify UI thread's control from worker thread
this.Dispatcher.BeginInvoke( <your delegate here>)
But i suspect that you can't do that in background worker thread as 'this' will mostly differ. So you may try this :
button.Dispatcher.BeginInvoke(new Action(()=>
{
//disable button here
}));
It is like worker thread send a message to tell UI thread to run the delegate.
One more thing, normally we disabled a control and re-enable a button after some process to avoid some unnecessary attached event/propertychanged event. So I suspect you may need this:
You can done that by removing event temporarily:
button -= button_click_event
and Re-add event after that
button += button_click_event
Hope this helps.
You can bind visibility property of controls which you want to disable and in MyExecutehandler function set property values to visibility.collapse
My app needs to load a usercontrol in the MainWindow on startup.
However the initialization of the usercontrol is slow. (not because of loading business data, I already separate the UI from business layer)
What I want to do is while waiting for the initialization of the usercontrol, a busy indicator will appear and will disappear when the initialization of the usercontrol is finished.
Right now I have a IsBusy property in the MainViewModel and is databind to the busyindicator in the MainWindow.
The child usercontrol is displayed via a contentcontrol.
presenter.Content = new ChildUserControl();
//presenter is the contentcontrol in MainWindow
However, how to run both the initialization and the display of busy indicator simultaneously? It seems that I need different threads to handle this issue.
However, running the initialization on a different thread while letting the main UI thread display the busy indicator will not work, since a child control in another thread cannot be placed within its parent control, which in this case is the MainWindow.
Any ideas on that?
I have implemented it myself. Namely I had scenario where we had XPS document loading(it was really slow) and then I had to implement spinner("busy indicator"). But that didn't work because they were on the same thread.
Now Dwayne come up with clever way how to multithread this, and it worked.
http://blogs.msdn.com/b/dwayneneed/archive/2007/04/26/multithreaded-ui-hostvisual.aspx
What about displaying the animated loading cursor? Windows already handles the threading on the mouse. I have had this problem before and I implemented my own loading animation on another thread but I had problems with rendering priorities causing the main executing code to be slow unless the mouse cursor was moving on top of the progress dialog. https://stackoverflow.com/a/307020/2247427
Surprisingly one can show more than one dialog at a time by putting the ShowDialog() call on the Dispatcher:
uiDispatcher.BeginInvoke(new Func<bool?>(myWindow.ShowDialog));
How come this works and still the UI remains running responding to user interaction once the dialog is shown (I would have thought not since ShowDialog() blocks the thread it is on which has to be the UI thread), one can even go on showing new dialogs:
Window myWindow;
for(int i = 0; i < 5; i ++)
{
myWindow = new Window();
uiDispatcher.BeginInvoke(new Func<bool?>(myWindow.ShowDialog));
}
And the UI is still responsive.
Is there something I should beware of relying on this behaviour? (I want to show one dialog on top of another when some background thread wants to - this works - the only unwanted behaviour seems to be when switching apps sometimes WPF does not know which dialog should be on top - but still allows you to bring one of the dialogs to the front by clicking on it which is unusual for a dialog as clicking outside a dialog is usually not allowed).
UPDATE: One issue I have come across is if you hide one of your dialogs the user can interact with all other Windows again! (not just the other dialogs). See: WPF Dialog not modal?
Showing a dialog does not block the UI thread -- otherwise you won't be able to interact with the dialog.
It merely marks the fact that there is a modal dialog outstanding, and that it should disable inputs to all other non-dialog windows.
If you shuff a ShowDialog call into the dispatcher, the dispatcher will allow an additional dialog to be created because you are not doing something which is prohibited when a modal dialog is outstanding -- which is to input into other non-dialog windows.
Your new dialog is fully functional, because it is a dialog, and you are not trying to input into non-dialog windows.
Switching applications should bring any modal dialog out to the front, but since you have more than one modal dialogs, the system will get confused as to which one should be top-most. I'd suggest you trap the activation event and just manually bring the necessary dialog top-most.
Should I use ApplicationCommands.Close for closing modal dialog boxes or is that command considered reserved for closing the application? If it is the latter, do folks create Close commands for each Dialog box or just a single Close command for all their modal dialog boxes?
Here is how WPF uses ApplicationCommand.Close:
WPF itself has no built in command handler for ApplicationCommands.Close, but
WPF executes the ApplicationCommand.Close RoutedCommand whenever it receives the Win32 message WM_APPCOMMAND with lParam=APPCOMMAND_CLOSE. This means that if any Win32 application sends you an APPCOMMAND_CLOSE, your ApplicationCommand.Close handler will be called.
The documentation for APPCOMMAND_CLOSE gives this definition:
Close the window (not the application).
I would assume WPF applications should treat ApplicationCommand.Close the same way, and that "the window" would include dialog boxes (it generally does in the world of Win32).
Why do you care about what the Win32 documentation says? It might be important in three situations:
Accessibilty scenarios
Keyboards that have a "close window" key
When the user has configured a combination of mouse buttons to send the "close window" command
So to answer your question: No, ApplicationCommand.Close is not reserved for closing the application. Its purpose is to close the window, including a dialog box window. So there is no need to create separate commands to close dialog boxes.
Many applications simply use a style in App.xaml to set a CommandBinding on thw Window class, and in the handler they end by calling ((Window)sender).Close(). This is a simple and elegant solution.
If you're just looking to bind a button click to close a dialog, you can set the IsCancel property on the button as recommended in the docs:
<Button IsCancel="True">Cancel</Button>
When you click that, it will close the dialog with a false result. If you want to close with a true result, one very simple way is adding a click handler and writing two (2) lines of code-behind. Your XAML is:
<Button IsDefault="True" Click="acceptButton_Click">OK</Button>
And the code-behind:
void acceptButton_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = true;
}
This will close the dialog and return a true result.
Since this is view code (close a window), this code-behind doesn't typically cause me any duress in my strict MVVM architectures. YDMV.
Closing an application is different than closing a dialog.
There is a built in command for dismissing dialogs. There is a big red 'X' at the top of any Window class that you create. When you hit that 'X' you generate a 'DialogCancelCommand' which is then handled by the 'OnDialogCancel' event handler inside the Window class. However, for reasons that are known only inside Redmond, the 'DialogCancelCommand' is an internal RoutedEvent.
I can't speak for other engineers, but I have reproduced the 'DialogCancelCommand' from the Reflected code so that I can close dialog boxes identically to the way the internal commands perform the same operation.
/// <summary>
/// Cancels a dialog.
/// </summary>
public static readonly RoutedCommand DialogCancelCommand = new RoutedCommand("DialogCancel", typeof(CoreCommands));