在OnNavigatedTo中更改模型后,Prism Xamarin Forms View未更新

时间:2017-07-29 22:07:52

标签: xamarin.forms prism

棱镜6.3.0

我导航到View,我在OnNavigatedTo方法中设置了Model的一些属性。问题是在设置模型的属性后,视图不会更新。

我的模型看起来像这样

public class Person
{
    public string Name { get; set; }
    public string Email { get; set; }
}

在我的ViewModel

public Person Model
{
    get => _model;
    set => SetProperty(ref _model, value);
}

OnNavigatedTo方法是

public void OnNavigatedTo(NavigationParameters parameters)
{
    var personModel = (Persom)parameters["Model"];

    _model.Email = personModel.Email;
}

在XAML中

<Entry Text="{Binding Person.Email, Mode=TwoWay}">
</Entry>

我也尝试过OnNavigatingTo方法,但我没有达到预期的效果。那么,当我导航到视图时,如何使用新数据更新视图?

2 个答案:

答案 0 :(得分:1)

使用setter而不是私有变量设置模型。

public void OnNavigatedTo(NavigationParameters parameters)
{
    var personModel = (Person)parameters["Model"];

    Model.Email = personModel.Email;
}

此外,您的XAML应该从Person.Email更改为Model.Email

=========== EDITED ============

您只设置不调用SetProperty的模型的电子邮件,因此不会使用新的电子邮件集更新视图。要更新视图,您需要将Person模型设置为以下内容:

public class Person : BindableBase
{
    public string Name { get; set; }

    private string _email;
    public string Email
    {
        get { return _email; }
        set { SetProperty(ref _email, value); }
    }
}

或者不只是在OnNavigatedTo中设置电子邮件,您可以设置Person对象。

public void OnNavigatedTo(NavigationParameters parameters)
{
    var personModel = (Person)parameters["Model"];

    Model = personModel;
}

答案 1 :(得分:1)

您可以使用Prism Quickstart Templates查看完整的工作示例。

您需要做一些关键事项:

直接绑定到您的Model的属性是一件很棒的事情(坦率地说,我在所有应用程序和演示中都做了一些事情)。但是,直接绑定到Model的属性意味着您需要确保Model是Observable(实现INotifyPropertyChanged)。

public class Person : BindableBase
{
    private string _email;
    public string Email
    {
        get => _email;
        set => SetProperty(ref _email, value);
    }
}

注意 如果您使用PropertyChanged.Fody(如QuickStart模板),您可以将其简化为(您不需要使用BindableBase,任何实现INotifyPropertyChanged的基类,或者甚至只是将类添加到类中工作):

public class Person : BindableBase
{
    public string Email { get; set; }
}

接下来,您需要设置ViewModel以接受要传递的参数。请注意,使用Prism 6.3,您有几个选择。

从Prism 6.3开始,INavigationAware成为两个新导航界面INavigatingAwareINavigatedAware的组合。正如名称所示,INavigatingAware处理即将发生的导航(在视图被推送到导航堆栈之前),而INavigatedAware处理刚刚发生的导航。结果是,如果在将视图推入堆栈时使用INavigatingAware.OnNavigatingTo更新模型,则会显示电子邮件,而使用INavigatedAware.OnNavigatedTo可能会导致显着的UI更新。

无论您选择哪种方法,都可以按照以下方式设置模型:

public class ViewAViewModel : BindableBase, INavigatingAware
{
    // This assumes you are using PropertyChanged.Fody as mentioned above
    public Person Model { get; set; }

    public void OnNavigatingTo(NavigationParameters parameters)
    {
        // Method 1:
        Model = parameters.GetValue<Person>("Model");

        // Method 2:
        if(parameters.TryGetValue<Person>("Model", out Model))
        {
            // do something
        }

        // Method 3:
        Model = new Person
        {
            Email = parameters.GetValue<string>("email");
        };
    }
}

注意 我应该注意,将Model的密钥与ViewModel的属性命名为Model并不重要。它可能是foobar并且仍然有效。重要的是关键匹配如下所示:

_navigationService.NavigateAsync("ViewA", new NavigationParameters
{
    { "foo", new Person { Email = "john@doe.com" } }
});

Model = parameters.GetValue<Person>("foo");

最后需要确保您不是绑定到对象类型而是绑定属性名称...您的视图的绑定上下文(您的ViewModel)使用属性名称Model引用Person模型,因此您的XAML那么看起来像这样:

<Entry Text="{Binding Model.Email}" />