【问题标题】:Link Xamarin properties from different ViewModels链接来自不同 ViewModel 的 Xamarin 属性
【发布时间】:2016-02-27 12:23:00
【问题描述】:

是否有可能以一种方式“链接”不同 ViewModel 的两个属性,这样当一个属性发生变化时,另一个属性也会发生变化。所以本质上,我希望不同 ViewModel 中的两个属性表现得好像它们是一个。

如果我可以在我的 ViewModels 中执行类似以下的操作,那就太好了:

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),但我不一定要导航到其他视图。不过,也许我可以以某种方式使用这个 MessagingCenter 来实现我的目标?

【问题讨论】:

    标签: c# xamarin mvvm xamarin.forms viewmodel


    【解决方案1】:

    这在您引用的我文章的最后一段中得到了解决。我使用一个简单的扩展方法来做到这一点。这方面的一个例子可以在文章的源代码示例中看到,在这个文件中: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 对象,由于在 Action lambda 表达式中捕获了引用,该对象又引用了 ModelView1 和 ModelView2。

    如果您确定这不会成为问题(可能两者一起超出范围),则无需担心。但是,如果您发现自己面临需要阻止 ModelView1 保持 ModelView2 固定的情况,那么您可以使用 Wea​​kReference 来做到这一点。同样,这不太可能成为问题,但如果您发现它泄漏内存,那么您可以将上面的内容更改为:

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

    【讨论】:

    • 好的,我试过了。我喜欢它,但我对访问其他 ViewModel 的方式并不完全满意——即通过构造函数传递它们。如何在 ModelView1 中获得对 ModelView2 的引用的最佳方式?
    • 属性更改可以随时连接 - 它不必在构造函数中。我通常只是为了方便而把它们放在那里。
    【解决方案2】:

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

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

    如果您需要更多帮助,请提供更完整的代码示例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-08
      • 1970-01-01
      • 2022-01-19
      • 2019-05-31
      • 1970-01-01
      • 2019-04-02
      • 2017-11-25
      • 1970-01-01
      相关资源
      最近更新 更多