链接来自不同视图模型的 Xamarin 属性

本文关键字:模型 Xamarin 属性 视图 链接 | 更新日期: 2023-09-27 18:36:26

是否可以只"链接"不同 ViewModel 的两个属性,以便当一个属性更改时,另一个属性也会更改。因此,从本质上讲,我希望不同 ViewModel 中的两个属性的行为就像它们是一个属性一样。

如果我能在我的视图模型中执行以下操作,那就太好了:

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

示例:在我的设置页面上,当我更改设置时,我希望新值在另一个页面的 ViewModel 中可用。

我知道我可以用第三层(模型)来实现这一点,但它感觉有点笨拙,我现在解决它的方式感觉不对(触发事件)。

我已经从这个页面实现了以下MVVM模式:http://www.wintellect.com/devcenter/krome/linking-property-change-notifications-in-xamarin-forms-or-wpfsilverlight。据我了解,作者说他的代码使之成为可能,但不幸的是他没有说明如何。

我也找到了这篇文章(http://blog.alectucker.com/post/2014/07/26/using-messageingcenter-in-xamarin-forms-for-viewmodel-to-viewmodel-navigation.aspx),但我不一定想导航到另一个视图。不过,也许我可以以某种方式使用这个消息传递中心来实现我的目标?

链接来自不同视图模型的 Xamarin 属性

这在您引用的我文章的最后一段中得到了解决。我使用一个简单的扩展方法来做到这一点。可以在本文的源代码示例中看到这方面的一个示例,在此文件中:https://github.com/Wintellect/XamarinSamples/blob/master/PropertyDependencyDemo%2FPropertyDependencyDemo%2FMvvm%2FObservableExtensions.cs

对于您的特定示例,它看起来像这样:

// using PropertyDependencyDemo.Mvvm;
// ... use the namespace above that contains the ObservableExtensions class
ModelView1
    .WhenPropertyChanges((a) => a.SettingX)
    .AlsoInvokeAction(() => ModelView2.SettingX = ModelView1.SettingX);

所有这些操作都是以名称安全的方式为您挂接到源视图模型的 PropertyChanged 事件。

但有一点要注意:您需要小心,不要造成无意中阻止对象被垃圾回收的情况。发生这种情况的原因是,在此示例中,ViewModel1 现在将有一个 PropertyChanged 处理程序,该处理程序引用一个 PropertyDependency 对象,该对象又引用 ModelView1 和 ModelView2,因为 Action lambda 表达式中捕获了引用。

如果您确定这不会成为问题(也许两者都超出了范围),那么就没有什么可担心的了。但是,如果您发现自己面临需要阻止ModelView1保持ModelView2固定的情况,则可以使用弱引用来实现。同样,这不太可能是一个问题,但是如果您发现它泄漏了内存,则可以将上述内容更改为以下内容:

// 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;
    });

我认为如果导航是行的(您只需要第 1 页第 2 页的信息),您可以使用消息传递中心做您想做的事情。

如果用户能够更改第 2 页中的数据(并在第 1 页中更新),则消息传递中心使用起来有点棘手。我认为您可以使用您提供的第一个链接。只需使用包含 ViewModel 中所有共享数据的抽象类即可。

如果您需要更多帮助,请放置一个更完整的代码示例。