OnViewModelPropertyChanged

Apr 8, 2011 at 8:03 PM
Edited Apr 8, 2011 at 8:05 PM

Hi,

i ve a ViewModel  that watches anotherViewModel. And anotherViewModel has a VMproperty with OnChange handler.

ViewModel's OnViewModelPropertyChanged triggers when VMproperty changes first time. But if i try to change VMproperty again it doesn't trigger.

Any Idea?

Note : i ve already used Both Catel 1.3 and Catel 1.4 (latest source)

Thanks.

Coordinator
Apr 9, 2011 at 6:26 AM

Do you have a small application that is able to reproduce the problem? Or even better, a failing unit test?

You should keep receiving the property changes, so there is something wrong here, but I cannot determine it without code.

Apr 9, 2011 at 6:55 AM
Edited Apr 9, 2011 at 6:56 AM
    public class WelcomePageViewViewModel : ViewModelBase
    {
           .
.
.

        void OnCardSwiped(string cardNumber)         {             CardNumber = cardNumber;         }         #region Properties         #region View model         // TODO: Register view model properties with the vmprop or vmpropviewmodeltomodel codesnippets         public string CardNumber         {             get { return GetValue<string>(CardNumberProperty); }             set { SetValue(CardNumberProperty, value); }         }         public static readonly PropertyData CardNumberProperty = RegisterProperty("CardNumber"typeof(string), (sender, e) => ((WelcomePageViewViewModel)sender).OnCardNumberChanged(e));         private void OnCardNumberChanged(EventArgs e)         {             if (CardNumber != null)             {                
.
.
.
.

             }         }
                .
.
.
.
    }


    [InterestedIn(typeof(WelcomePageViewViewModel))]
    public class SelectLanguagePageViewViewModel : ViewModelBase
    {
 
                .
.
.
.
        protected override void OnViewModelPropertyChanged(IViewModel viewModel, string propertyName)        
{
//When CardNumber changes in WelcomePageViewViewModel This Handler runs just one time (on first change)


             if (propertyName == "CardNumber")  
            {
                
.
.
.
.

             }
        }  
                .
.
.
.
    }
Apr 9, 2011 at 8:50 AM

i wrote a little sample  and it works so i am searching my code deeply why it doesnt fire  ..

Coordinator
Apr 10, 2011 at 10:39 AM

Sample seems to work fine indeed. Is the "WelcomePageViewModel" view-model in your real application a view-model that is dynamically constructed? If you want, you can send your application and I will investigate why it is failing. Of course we will treat your code confidentially.

If you want me to take a look at it, just contact me via CodePlex and I will provide you my e-mail address.

Apr 10, 2011 at 7:56 PM

Horrik, i am very pleased that you want to help me. But the Code is DB dependent.

i prepared a new sample . Catel.Examples.OnViewModelPopertyChanged is like my App and it behaves the same. in first time OnViewModelPopertyChanged triggers but the rest not.

i use Bornanders.Carousel to show views in 3D.

I really enjoy learning your great Catel MVVM Lib.

Thanks in Advance

Coordinator
Apr 10, 2011 at 8:51 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Coordinator
Apr 10, 2011 at 10:52 PM

Your problem is very, very complex. I will try to explain the solution and why it happens. First of all, this led to a bug where UserControls that were unloaded but not disposed (and thus not constructed next time) were holding previous versions of the view-model. This way, you are able to "cheat" and provide values between the view-models. This is what happens in your initial project:

  1. VM1 is constructed
  2. VM2 is constructed that watches VM1
  3. You change, so VM1 notifies VM2 of it's change, which takes over the change, the VM2 now has the right card value
  4. VM1 is closed (but never removed as datacontext)
  5. VM2 is then closed (but never removed on the next close)

Now you have a situation where you see the first number on the second VM every time (which is the strange issue that you saw that it only updates once).

I have fixed the bug and checked it in, but this does not solve your problem and I will tell you why (and why I call it "cheating"). You store the CardNumber in the view-models only, so you don't maintain the state anywhere in memory or the data. In the old situation (before the bug fix), you had the luck that the view-models were not removed from memory correctly. However, it is very important to maintain your state (for example, the current state) somewhere. Everytime you switch from panel, the user controls are unloaded (this is WPF behavior), and then the view-models are unloaded as well. We need to close the view-models because there is no "Close" event for a user control, and you never know when a control is actually unloaded for the last time (everytime can be the last).

What you need to do is store the state of the current card somewhere in memory or persistence store (but since it's probably about a game, I advise you use memory). Then, in the Initialize of the view-models, you use the memory store (this is your model) to retrieve the current card number. Since the two view-models are not alive at the same time (there is only 1 view at a time), you cannot use the technique to communicate between view-models (because what is to communicate). It is better to do the following:

  1. In WelcomePageViewModel initialize, load the current card from memory (for example, a singleton class)
  2. In the WelcomePageViewModel.Save or Close, save the current card to memory
  3. In the SelectLanguagePageViewModel.Initialize, load the current card from memory again
  4. etc

The viewmodel to viewmodel communication is only useful for view-models that are alive at the same time (for example, in a tabbed environment or in a parent/child relationship of view-models).

I hope this provides some more information on how to implement MVVM correctly. If you need any more help, just let us know.

Coordinator
Apr 10, 2011 at 10:58 PM

For your convenience, I have added a "working" example in the issue. You can find the issue here.