简体   繁体   中英

Link Xamarin properties from different ViewModels

Is it possible to just "link" two properties of different ViewModels in a way such that when one property changes, the other one changes too. So in essence, I want two properties in different ViewModels behave as if they were one.

It would be nice if I could just do something like the following in my ViewModels:

WhenPropertyChanges(() => SettingX).CopyValueTo(() => ModelView2.SettingX);

Example: On my settings page, when I change a setting, I want the new value to be available in the ViewModel of another page.

I know I can achieve that with the third Layer (Model), but it feels a bit clunky and the way I solved it for now doesn't feel right (Firing events).

I've implemented following MVVM-Pattern from this page: http://www.wintellect.com/devcenter/krome/linking-property-change-notifications-in-xamarin-forms-or-wpfsilverlight . As far as I understood, the author says his code makes it possible, but unfortunately he doesn't show how.

I also found this article ( http://blog.alectucker.com/post/2014/07/26/using-messageingcenter-in-xamarin-forms-for-viewmodel-to-viewmodel-navigation.aspx ), but I don't necessarily want to navigate to the other View. Still, maybe I can use this MessagingCenter somehow to achieve my goal?

I think if the navigation is lineare ( you only need the information of page 1 in page 2 ) you can use the MessagingCenter to do what you want.

If the user is able to change the data in the page 2 ( and be updated in the page 1 ) the messagingCenter is a little to tricky to use. I think you can use the first link you provide. Just use an abstract class with all shared data in your ViewModels.

If you want more help put an more completed code example.

This is addressed in the final paragraph of my article that you reference. I use a simple extension method to do it. An example of this can be seen in the source code example from the article, in this file: https://github.com/Wintellect/XamarinSamples/blob/master/PropertyDependencyDemo%2FPropertyDependencyDemo%2FMvvm%2FObservableExtensions.cs

For your specific example, it would look something like this:

// using PropertyDependencyDemo.Mvvm;
// ... use the namespace above that contains the ObservableExtensions class

ModelView1
    .WhenPropertyChanges((a) => a.SettingX)
    .AlsoInvokeAction(() => ModelView2.SettingX = ModelView1.SettingX);

All this does is hook into the PropertyChanged event of the source viewmodel for you in a name-safe way.

One word of caution though: you need to be careful to not create a situation where you inadvertently prevent an object from being garbage collected. The reason this can happen is that in this example, ViewModel1 will now have a PropertyChanged handler that references a PropertyDependency object that in turn references both ModelView1 and ModelView2 due to the captured references in the Action lambda expression.

IF you know for sure that this won't be a problem (perhaps both go out of scope together), then there is nothing to worry about. But if you find yourself facing a situation where you need to prevent ModelView1 from keeping ModelView2 pinned, then you can do so using a WeakReference. Again, this is unlikely to be a concern, but if you find it leaking memory then you can change the above to this:

// assuming "TModelView" is the class name of the viewmodels

var wr = new WeakReference<TModelView>(ModelView2);
ModelView1
    .WhenPropertyChanges((a) => a.SettingX)
    .AlsoInvokeAction(() => {
        TModelView mv;
        if (wr.TryGetTarget(out mv))
            mv.SettingX = ModelView1.SettingX;
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM