0

我的目标是访问整个应用程序的可绑定属性。但是我当前的框架 ViewModel 实例创建了多次

我的要求:我在bottomTray(CheckuoutViewModel)中有购物车数量我想在应用页面中的任何位置增加购物车数量,但是在此购物车数量在返回点击时不会更新,它仅适用于前向导航,CheckoutViewModel背后的原因每次都创建实例。这样我就可以尝试更早地进行即时创作。

这里我列出了示例 ViewModel 和调用方法

  1. 登录视图模型
  2. Checkuout ViewModel(此视图模型适用于所有页面)
  3. BaseNavigationViewModel(其 BaseViewModel)

截至目前,我每次都在调用 BindinContext 时,

  • 新的登录视图模式(导航)
  • new CheckoutViewModel(navigation) 当像 ViewModel Locator 这样的应用程序启动时间时,如何创建所有 ViewModel 实例?

我试过了

public static ViewModelLocator Locator
    {
        get { return locator ?? (locator = new ViewModelLocator()); }
    }

和 ViewModel 定位器

public ViewModelLocator()
    {
        navigation = App.Current.MainPage.Navigation;
    }
internal CustomTabBarViewModel CustomTabBarVM
    {
        get
        {
            return customTabBarVM ?? (customTabBarVM = new CustomTabBarViewModel(navigation));
        }
    }

和 CustomTabBar.xaml.cs

public CustomTabBar()
    {
        viewModel = App.Locator.CustomTabBarVM;
        InitializeComponent();
        BindingContext = viewModel;
    }

和期望

App.Locator.CustomTabBarVM.BadgeCartCount = OrderObject.Instance.ORDER_OBJECT.Items.Count;

这种方法运行良好,但会产生一些导航问题

4

2 回答 2

2

单例实例是几乎所有 MVVM 框架(Prism、FreshMVVM 等)的共同特征。如果你没有使用框架(如果你没有,我强烈建议你考虑使用一个),下面是一个解决方案。

要获取 ViewModel 的单个实例,您可以使用App该类来托管对象并在需要时访问它。

  • 创建 ViewModel 的公共静态属性:
public static MyViewModel MyViewModelInstance { get; }
  • 在应用程序的构造函数中创建一个实例
public App()
{
    InitializeComponent();

    MyViewModelInstance = new MyViewModel();

    var myPage = new MyPage()
    {
        BindingContext = MyViewModelInstance
    };

    var navPage = new NavigationPage(myPage);

    MainPage = navPage;
}
  • 每当您创建新页面时,访问共享实例
// This method is just an example of how you might create a new page and wire up the view model
async void GoNextClicked(System.Object sender, System.EventArgs e)
{
    var myPage = new MyPage()
    {
        BindingContext = App.MyViewModelInstance
    };

    await this.Navigation.PushAsync(myPage);
}

这种方法有一些注意事项,您是在应用程序加载时创建实例,而不是在需要时创建实例(急切加载)。因此,性能优化将Lazy<T>用于处理这些对象的创建。然而,这是已经在 MVVM 框架中为您编写的逻辑,它们可以帮助您,您应该使用它们。

延迟加载

您可以通过延迟加载视图模型在启动时节省内存和性能,这是重写以支持此模式的示例:

public static MyViewModel MyViewModelInstance
{
    get => _myViewModelInstanceFactory.Value;
}

private static Lazy<MyViewModel> _myViewModelInstanceFactory = new Lazy<MyViewModel>(() => new MyViewModel(), true);

public App()
{
    InitializeComponent();

    var myPage = new MyPage()
    {
        BindingContext = MyViewModelInstance
    };

    var navPage = new NavigationPage(myPage);

    MainPage = navPage;
}

现在这个对象在被你的代码访问之前不会被创建,一旦它被访问,一旦它已经被创建,并且将在你的应用程序生命周期的其余部分继续存在于内存中。

于 2021-08-02T10:24:52.467 回答
0

Axemasta对共享视图模型实例的重用有很好的回答。

我将针对一条评论中给出的基本需求提供另一种方法:如何拥有静态属性(因此该值是通用的),以及在绑定到实例时绑定到它。

如果您确实想要为每个新页面使用不同的 CheckoutViewModel,请使用此方法。例如,如果有其他属性应该设置不同,具体取决于页面。

public class CheckoutViewModel :  : INotifyPropertyChanged  // or your MVVM library's base class for ViewModels.
{
    public static int SharedCount { get; set; }

    public void IncrementCount()
    {
        Count = Count + 1;
    }

    public int Count {
        get => SharedCount;
        set {
                // Exact code might be simpler if using an MVVM library.
                if (SharedCount != value)
                {
                    SharedCount = value;
                    OnPropertyChanged("Count");
                }
            }
        }
    }
}

限制:这假设只有 CheckoutViewModel 的当前实例是可见的;如果您需要“通知”其他视图(更新其他 CheckoutViewModel 实例),那么您将需要“发布/订阅”解决方案。在 Xamarin Forms 中,这样的解决方案之一是MessagingCenter

于 2021-08-02T11:17:07.443 回答