IPleaseWaitService.Hide after all InterstedIn Classes

Topics: Issues / bugs
Jun 27, 2012 at 9:57 AM
Edited Jun 28, 2012 at 10:50 AM

Hello

In an ViewModel when a Property has Changed i show the IPleaseWaitService. Some other viewmodels are InterestedIn that property. So now i want the to hide the IPleaseWaitService after all InterestedIn Classes are ready with the OnViewModelPropertyChanged Method.

How to solve this?

Jun 27, 2012 at 10:04 AM

Show the please wait window *before* setting the property, and hide it afterwards. It is all synchronous, so that is the safest way.

Jun 28, 2012 at 10:50 AM
Edited Jul 25, 2012 at 2:42 PM

Yes. but the problem is that the proptery is set in  XAML with a binding. So how can I show the wait window before and hide it after?

Jun 28, 2012 at 10:55 AM

That is hard. The only thing you can do is if you are in WPF, is use something like this:

1) Override OnPropertyChanging => show pleasewaitservice

2) Override OnPropertyChanged => call base, then hide pleasewaitservice

Jul 20, 2012 at 1:52 PM
Edited Jul 20, 2012 at 2:00 PM

Hello again to this Topic.

I try this:

        protected override void OnPropertyChanging(PropertyChangingEventArgs e)
        {
            base.OnPropertyChanging(e);
 
            if (e.PropertyName == "ActiveProfile")
            {
                _wait.Show("Loading");
            }
        }
 
 
        protected override void OnPropertyChanged(AdvancedPropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);
 
            if (e.PropertyName == "ActiveProfile")
            {
                _wait.Hide();
            }
        }

Problem is that at startup the ViewModel is called twice. At the moment I don't know why. ( maybe a bug :-) )  But no matter. The Problem is that _whait. Show()  is called also twice. Only after that the _wait.Hide is called.  The result is a Exception. I see there is a showCounter, but this Property is always 0.

Jul 20, 2012 at 2:02 PM

One moment. The Problem is that constructor of my ViewModel called Twice when i call _wait.Show(). ?!

Jul 20, 2012 at 2:52 PM
Edited Jul 20, 2012 at 2:54 PM

Ok. One more awareness. Set: CloseViewModelOnUnloaded = false; So  protected override System.Type GetViewModelType() is only called once.

But next problem.

IPleaseWaitService _wait = IoCHelper.UnityContainer.Resolve<IPleaseWaitService>();

public PageProfileViewModel() 
{                 
    _gateway = IoCHelper.UnityContainer.Resolve<DataGateway>()

    var config = _gateway.GetActiveConfiguration();
    if (config != null)
        ActiveProfile = config.Profile;

    var something = 5;
}

protected override void OnPropertyChanging(PropertyChangingEventArgs e)
{
    base.OnPropertyChanging(e);
 
    if (e.PropertyName == "ActiveProfile")
        _wait.Show("Profil wird geladen");
}

When I set the ActiveProfile Property in the constructor, the OnPropertyChanging is called and the _wait.Show(). The constructor is not ended and it is called twice!?

Jul 23, 2012 at 10:53 AM
Edited Jul 23, 2012 at 11:00 AM

I have dubbged Catel with .Net Refelctor. No i stopped at following point:

Class: PleaseWaitHelper

Method: private void ShowWindow(int percentage)

Call: this.PleaseWaitWindow.Show();

It's not possible for me to debug this Method Show of Class Window. It's not working with .Net Reflector. I don't know why. But in this method there is thrown an exception.

Class ViewModelFactory / Method CreateViewModel catch this Exception.

With MissingMethodException and Info "No constructor found". But  than its called the (missing!?) constructor again.

I think the problem is that Window.Show() is also thrown a MissingMethodException.

Jul 23, 2012 at 2:24 PM

To complex :-)

I try to make an repro and open an new issue.

Jul 23, 2012 at 6:35 PM

Interesting. If you have a repro, that would be great.

Probably a view model (with the same input parameters) and a view are sufficient to demonstrate the problem.

Jul 24, 2012 at 7:42 AM

Repro and issue created: http://catel.codeplex.com/workitem/7170

Jul 25, 2012 at 3:14 PM

Thanks, we will look into it ASAP.

Aug 20, 2012 at 2:01 PM
Edited Aug 22, 2012 at 7:48 AM

You have closed the issue. http://catel.codeplex.com/workitem/7170.

I  tried the example with the fix. Two Problems.

1. Why is the constructor of PageProfileViewModel called twice.

2. Why is there no text  ("Loading") in the PleaseWaitServie Window?

Aug 21, 2012 at 8:22 AM

I will look into this.

Aug 27, 2012 at 9:25 AM

Do you  found something? It's very important for me.

Aug 27, 2012 at 9:36 AM

Not yet. I have invested the double loading a few minutes, but forgot it due to other priorities. The issue is probably because the UI-thread is immediately busy. I will try to create the textbox on a different thread as well, but it can get quite messy.

Sep 1, 2012 at 3:59 PM

It took me a while to figure this out, sorry for that. 

The issue basically is this:

1) Your VM is created the first time because the control data context has changed (control not loaded yet)

2) VM gets instantiated, but inside the ctor, you call Active = "value". This causes the VM to show the UIVisualizerservice. Because the view is not yet loaded, WPF forces the loading of the view.

3) The OnViewLoaded handler kicks in, and the ViewModel is not yet set (remember, we are still creating it)

4) You now have 2 view models.

You can fix this issue by using Initialize instead of the ctor to set values. Then the view is loaded by WPF and you can freely set values. Another way is to keep an internal _showBusyIndicator which you enable in the Initialize method.

Sep 4, 2012 at 9:47 AM

I use the Initialize Method. Perfect. Thanks a lot.

Sep 12, 2012 at 10:11 AM

One more Problem to this topic:

So that are the calls:

OnPropertyChanging => show pleasewaitservice

OnPropertyChanged => call base, then hide pleasewaitservice

I set a value to the Property. The new value is the same as the old. Now the OnPropertyChanging is called but never OnPropertyChanged.

Sep 12, 2012 at 7:38 PM

You call the base methods as well? Or do you only override without calling the base?

Sep 13, 2012 at 7:54 AM
Edited Sep 13, 2012 at 12:14 PM

Yes, I call the base classes 

base.OnPropertyChanging(e);

and  

base.OnPropertyChanged(e);

 

Sep 13, 2012 at 8:10 AM

Then please provide a repro so I can test it. Or does the existing repro also fail to set the property?

Sep 14, 2012 at 4:21 PM

I tried your last repro (the one with the close button), and it seems to set the value just fine. Am I missing something there?

Sep 17, 2012 at 10:55 AM
Edited Sep 17, 2012 at 10:56 AM

Yes, you missing something there. OnPropertyChanging is not called when you don't change a value.

So add a new property. OtherValue for example. Add a button with command. In the command you copy the value of active to other value.

and change this

        protected override void OnPropertyChanging(AdvancedPropertyChangingEventArgs e)
        {
            base.OnPropertyChanging(e);
 
            if (e.PropertyName == "OtherValue")
            {
                _wait.Show("Loading");
            }
        }
 
        protected override void OnPropertyChanged(AdvancedPropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);
 
            if (e.PropertyName == "OtherValue")
            {
                _wait.Hide();
            }
        }

private
 void OnOtherValueChanged()         {             Thread.Sleep(2000);         }

So the first time you press the button, its everything ok but not the second time. OnlyOnPropertyChanging is called not OnPropertyChanged.

Oct 31, 2012 at 9:50 PM

Now I finally understand your issue. I will see if I can fix it.

Oct 31, 2012 at 10:06 PM

Issue fixed, currently releasing a new nuget package. I will look into your other issues soon.