WPF loading panel and UI freeze - wpf

I have a mainwindow which displays a 'Please wait' panel containing a loading gif whenever I do some work in a Task. The gif plays fine when the data is being compiled, but when the INPC logic to refresh the UI controls is being executed (thus on the main UI thread), the app freezes for a split second and my gif does not play smoothly anymore.
For instance, I am following the MVVM pattern, I have a datagrid in my view which is binded to an ObservableCollection MyBindedCollection. In the constructor of my viewmodel which runs in a Task, I create a tmp observable collection and when the process is finished, I set the variable MyBindedCollection to tmp (thus not adding one by one my items to it). The INPC logic is of course in the setter of my property MyBindedCollection.
Is there anyway to prevent this? any idea would be appreciated.

#ZoolWay yes, no way around that I'm affraid. I'll just fade out my wait panel and thread.Wait enough time for the animation to finish before displaying my content. Thus it'll appear smooth. Thanks for your time.

Related

WPF: How to update UI without blocking animations

in my WPF application I have a ListView with a GridView as it's View. The ItemsSource of the ListView is bound to an ItemsCollection in the ViewModel.
This GridView has a lot of columns and the ListView can have a lot of items.
When the windows is loading or the user updates this ListView I show a loading animation while retrieving the new data from the server and updating the ItemsCollection in the ViewModel with the new data.
This retrieving of data is already done asynchronously, so the loading animation keeps spinning. But as soon as the data is retrieved and the binding is to update the ListView, the loading animation freezes until the update of the UI is finished.
How can I make my loading animation keep spinning even when the binding updates the UI?
Thank you for your help.
EDIT:
Well, that binding runs in the main thread, the same thread your animation runs.
Clearly my previous solution wont help you. You will have to find a way to reduce the time it takes to rendering view. Share some working code, maybe someone can help you.
Other alternative is to stop the animation and show something static. That way you hide the problem. Its not a great solution, but if you don't find other, this could your only one.

Show Loading Image when TreeView Node is clicked in WPF

The question is we have a WPF application, which has Tree View. On the click of node Report gets generated which has no time interval (I mean no clue how much time it will take). So I am planning to show a Loading.gif file on the window till the report is generated.
How can I make the image (.gif) visible while the main window process to show the report and after showing the report I need to hide the image.
Do you have any other alternate method to do so.
Appreciate your help in advance.
You can make use of Extended WPF Toolkit's BusyIndicator.
Here's a sample of how to make async multi-threaded treeview -> http://www.codeproject.com/KB/WPF/ThreadedWPFExplorer.aspx
The general technique for this is:
1) Create an IsBusy property in the view model for your window; make sure it raises PropertyChanged when it changes.
2) In the code executed when the item is clicked, use a BackgroundWorker to run the long-running task.
3) Before calling BackgroundWorker.DoWork(), set IsBusy to true. In the event handler called when the BackgroundWorker.RunWorkerCompleted is raised, set IsBusy to false.
4) In the DataTemplate for the window, add a Style with a DataTrigger bound to IsBusy, and use that to control the visibility of the image.
Note that you may be able to move IsBusy (and the long-running task and the BackgroundWorker) to the item view model instead of the window view model, and add a "Loading" animation to the DataTemplate for the item.
If you do this, the user can start multiple items loading simultaneously, and the entire application doesn't lock up just because one item in the TreeView got clicked on. (Of course, you have to deal with any multithreading issues involved in generating multiple reports simultaneously).

How to show some animation while control is rendering?

I have WPF ListBox that shows a lot of data. I need smooth scrolling, so I've set ListBox.ScrollViewer.CanContentScroll to False that disables virtualization. Now when I open the tab where this ListBox is placed, I see nothing for few seconds because ListBox is loading/creating items/rendering. I also have a control that shows some animation that indicates that application is running and user should wait a bit.
How can I show this control while ListBox is not available?
Add a Grid in the location of your list box and place inside it your ListBox and your animation control. This way they are placed in the same location. The animation control should be on the top of the z-order and so displayed. Once the ListBox has finished loading you would then hide the animation control and so the ListBox would show instead. Any time you need to perform another long operation you set the animation control to visible again.
Clean shutdown in Silverlight and WPF applications
Check how the author of this application did it via code maybe it can help you though it is different scenario.

Error window show modal in MVVM WPF

I have implemented my MVVM error message as a message dialog that subscribes to error messages via a mediator class, so that other viewmodels can notify it if any errors occur.
When an error occurs, I set the visibility attribute in the viewmodel to Visible, to display the error window. This is all bound in the Error window from the viewmodel.
However, this window is NOT modal! I need to show it as a dialog and not just set the visibility to true - is there any kind of binding I can do, even if I have to extend the functionality of the window? I'd rather not break MVVM if I can avoid it.
Thanks!
The View/ViewModel split is meant to divide look from functionality. I firmly believe the Window is functionality and look rolled into one. For instance, what if in your ErrorMessageViewModel, you had this code that executes when there are errors:
class WindowViewModel : Window
{
}
.
.
.
WindowViewModel newDialog = new WindowViewModel();
newDialog.Content = myErrorListViewModel;
newDialog.Parent = mainWindowViewModel;
newDialog.ShowDialog();
So the contents of the dialog is the ViewModel for your error list. Define your View as a data template that automatically applies itself to the error list ViewModel.
Doesn't that look like MVVM?
The fact is, the Window class is a ViewModel for the Window you see on the screen. By changing the properties of the Window object, it affects the "view" just like if the properties of the WindowView were bound to a WindowViewModel. The only thing missing is the ability to "restyle" the Window using WPF, and it doesn't matter how hard you try to implement it, you're not going to be able to do that. The user can restyle a Window by modifying their desktop theme, but you're not in control of it. The best you can do is turn off the chrome and/or make it full screen.
You find an example how windows (don't matter if they are modal or not) are shown, in the ViewModel example of this project:
WPF Application Framework (WAF)
http://waf.codeplex.com
I am also working on a MVVM project where I need modal dialogboxes or messageboxes. I have found the following way of solving it:
The software uses only one window. The layout root element is a Grid with no row- or columndefinitions. The grid has three children:
A dockpanel that contains all the usual stuff like menus, tabbed views, status bar and so on.
A grid that has a gray background and a 50% opacity. This is used as a veil to cover the dockpanel when a modal box is in effect. The veil grid is usually collapsed.
A grid holding modal views, this is usually collapsed.
The viewmodel for the main window has a member called Modal. If this is null, the two grids for modal use are collapsed through databinding and a converter for Visibility.Collapsed.
When the program wants to display for example a modal message box, a MessageBoxViewModel is instantiated and assigned to MainViewModel.Modal. The MessageBoxViewModel has a Command for an OK-button. This Command raises an event that sets the MainViewModel.Modal to null again.
The veil grid occludes the main DockPanel, so that no controls outside the Modal control accept input.
Your program can either run a messagepump until OK is pressed, or the OK-Command can trigger the next. There are many ways of solving different needs, but the Model-ModelView solution should support them.
I feel that this is as good a model of the view in the modal mode as one can hope for.
I made a behhavior to tie some modal dialogs to the command.
http://www.clr-namespace.com/post/MVVMModal-dialog-before-running-Command.aspx
<Confirm:Confirm IsConfirm="{Binding ElementName=checkBoxConfirm, Path=IsChecked}"
Command="{Binding Path=ButtonCommand}"
CommandParameter="{Binding ElementName=textBoxParameter, Path=Text}"
ConfirmMessage="Are you sure you want to fire the command?"
ConfirmCaption="Question" >
</Confirm:Confirm>
In my recent blog post you can find simple solution for Modal Dialogs and Message Boxes in MVVM for Silverlight but this can be simply reused in WPF:
Modal dialogs with MVVM and Silverlight 4
i'm using the same method as Scott Whitlock.
there is just one more important property to set:
class ModalDialog: Window
{
}
.
.
.
var dlg = new ModalDialog {
Content = viewModelName,
**TopMost = true,**
Parent = mainWindowViewModel
};
dlg.ShowDialog();

Where does the presentation logic go for the View-Model-ViewModel pattern?

In the View-Model-ViewModel, actions are essentially executed by the viewmodel that is bound to the view. However, where would the "presentation logic" go since the code behind isn't used and the viewmodel has no reference or knowledge of the control that invoked it?
For example, what if I wanted to animate another control when a button is clicked. Would this still go in the code behind?
To expand on Justin Niessner's comment, I'd be using a trigger to achieve this animation as it's all UI bound.
Think about this:
Where would you put code so that when someone mouses over a button it becomes hilighted?
What about code for "depressing" that button when it is clicked?
These and your question are all variations on a theme, so I'd say do it in the GUI.
However, there's one exception to this rule. If the "animation" is a processing animation, then it might be worth tying it to the ViewModel so the ViewModel can control how long the animation runs while it's processing something. Otherwise do it in the GUI.
EDIT: Based on your comment. Ok so the animation should run off a property in the ViewModel, not the button click event. The Click should start the processing in the ViewModel through a command, and the execute code for that command should set a processing flag property on the ViewModel. Then the View can bind to that processing flag and display a progress bar or whatever when that flag is set.

Resources