在Xamarin.Forms中处理对象

kal*_*sov 6 c# xamarin xamarin.forms

我正在寻找在Xamarin Forms应用程序中处理对象的正确方法.目前我正在使用XAML和MVVM编码风格.然后从我的视图模型中,我通过内置服务定位器(DependencyService)获得对一次性对象的引用.理想情况下,我应该能够从我的视图模型中调用对象上的Dispose(),但是其他解决方案(如附加到ContentPage.OnDisappearingNavigationPage.Popped)也是可行的.

Cal*_*don 13

几周前我有几乎相同的要求。我想确保当页面关闭时,我的视图模型中的事件订阅将被取消订阅。经过大量研究,我的结论是最简单的解决方案是使用 ContentPage.OnDisappearing 方法。

正如您指出要处理的对象在您的 ViewModel 中,因此您需要一些基础设施来确保您的 ViewModel 在它消失时得到通知。为此,我定义了我的视图模型的基本实现,它有两个关键方法 OnAppearing 和 OnDisappearing(注意这是一个类而不是接口,因为我有其他基本功能,例如 IPropertyNotify 实现 - 此处未显示)。

public class ViewModelBase
{
    /// <summary>
    /// Called when page is appearing.
    /// </summary>
    public virtual void OnAppearing()
    {
        // No default implementation. 
    }

    /// <summary>
    /// Called when the view model is disappearing. View Model clean-up should be performed here.
    /// </summary>
    public virtual void OnDisappearing()
    {
        // No default implementation. 
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我将 ContentPage 子类化并覆盖 OnAppearing 和 OnDisappearing 方法,然后使用它们来通知我的视图模型。

public class PageBase : ContentPage
{
    /// <summary>
    /// Performs page clean-up.
    /// </summary>
    protected override void OnDisappearing()
    {
        base.OnDisappearing();

        var viewModel = BindingContext as ViewModelBase;

        // Inform the view model that it is disappearing so that it can remove event handlers
        // and perform any other clean-up required..
        viewModel?.OnDisappearing();
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();

        // Inform the view model that it is appearing
        var viewModel = BindingContext as ViewModelBase;

        // Inform the view model that it is appearing.
        viewModel?.OnAppearing();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后当你实现一个页面时,只需确保它是 PageBase 类型:

<?xml version="1.0" encoding="utf-8" ?>
<pages:PageBase xmlns="http://xamarin.com/schemas/2014/forms"
          xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
          xmlns:controls="clr-namespace:Forms.App.Controls;assembly=Forms.App"
          xmlns:converters="clr-namespace:Forms.App.Converters;assembly=Forms.App"
          xmlns:pages="clr-namespace:Forms.App.Pages;assembly=Forms.App"
          x:Class="Forms.App.Pages.LogonPage"
          NavigationPage.HasNavigationBar="False"
          Title="Logon">
Run Code Online (Sandbox Code Playgroud)

然后在您的 ViewModel 中,您可以覆盖 OnDisappearing 方法并处理您的对象:

public class FormViewModel : ViewModelBase
{
    public override void OnDisappearing()
    {
        base.OnDisappearing();

        // Dispose whatever objects are neede here
    }
}
Run Code Online (Sandbox Code Playgroud)

需要注意的一件事 - 如果您使用堆栈导航,当您将另一个页面堆叠在当前页面的顶部时会调用 OnDisappearing 方法(毕竟您的页面暂时消失了)。因此,您将需要满足这一点,并且在这种情况下可能不会处理您的对象。但是,如果您没有在页面顶部堆叠任何内容,则无需担心。就我而言,它只是事件订阅,所以我在 OnAppearing 中附加了事件处理程序,并在 OnDisappearing 上将它们分离。

我希望能帮到你!


Nic*_*ers 6

当绑定到 ListViews 或 Labels 的值随着页面/片段被处理而改变时,我们正在处理表单中的对象异常。我假设您可以在我们删除绑定的同一位置处理 ViewModel 中的对象。

protected override void OnParentSet()
{
    base.OnParentSet();

    if (Parent == null)
    {
        //Clear a bunch of bindings or dispose of ViewModel objects 
        BindingContext =
            _listView.ItemsSource = null;
    }
}
Run Code Online (Sandbox Code Playgroud)