在Prism 6处,ObservesProperty方法未观察模型的属性 [英] ObservesProperty method isn't observing model's properties at Prism 6

查看:129
本文介绍了在Prism 6处,ObservesProperty方法未观察模型的属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习Prism MVVM,我正在制作一个包含2个字段和一个按钮的窗口,当这两个字段不为空时,该窗口将启用.

I'm trying to learn Prism MVVM, and i'm making a window with 2 fields and a button, that gets enabled when this two fields aren't empty.

问题是我找不到使方法ObservesProperty()在对象(在这种情况下为Pessoa)上工作的方法. CanExecuteAtualizar()方法仅在应用程序启动时被调用,并且当我编辑文本字段NomeSobrenome时,按钮什么也没有发生,并且该方法未触发...

The problem is that i can't find a way to make the method ObservesProperty() work on an object (Pessoa in that case). The CanExecuteAtualizar() method only gets called at the app startup, and when i edit the textfields Nome or Sobrenome nothing happens to the button and the method isn't fired...

我试图在没有模型的情况下工作,将NomeSobrenomeUltimaAtualizacao属性直接放在ViewModel中,并且工作正常,根据方法CanExecuteAtualizar的返回禁用按钮,但是我希望将其与模型一起使用.有办法吗?

I tried to work without a model, putting the Nome, Sobrenome and UltimaAtualizacao properties directly in the ViewModel and it works fine, disabling the button according to the return of the method CanExecuteAtualizar, but i wanted to use it with a model instead. Is there a way to do this?

ViewAViewModel.cs

public class ViewAViewModel : BindableBase
{
    private Pessoa _pessoa;

    public Pessoa Pessoa
    {
        get { return _pessoa; }
        set { SetProperty(ref _pessoa, value); }
    }

    public ICommand CommandAtualizar { get; set; }

    public ViewAViewModel()
    {
        Pessoa = new Pessoa();
        Pessoa.Nome = "Gabriel";
        CommandAtualizar = new DelegateCommand(ExecuteAtualizar, CanExecuteAtualizar).ObservesProperty(() => Pessoa.Nome).ObservesProperty(() => Pessoa.Sobrenome);
    }

    public bool CanExecuteAtualizar()
    {
        return !string.IsNullOrWhiteSpace(Pessoa.Nome) && !string.IsNullOrWhiteSpace(Pessoa.Sobrenome);
    }

    public void ExecuteAtualizar()
    {
        Pessoa.UltimaAtualizacao = DateTime.Now;
    }
}

Pessoa.cs

public class Pessoa : BindableBase
{
    private string _nome;

    public string Nome
    {
        get { return _nome; }
        set { SetProperty(ref _nome, value); }
    }

    private string _sobrenome;

    public string Sobrenome
    {
        get { return _sobrenome; }
        set { SetProperty(ref _sobrenome, value); }
    }

    private DateTime? _ultimaAtualizacao;

    public DateTime? UltimaAtualizacao
    {
        get { return _ultimaAtualizacao; }
        set { SetProperty(ref _ultimaAtualizacao, value); }
    }
}

ViewA.xaml

<UserControl x:Class="PrismDemo.Views.ViewA"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:PrismDemo.Views"
             mc:Ignorable="d"
             d:DesignHeight="100" d:DesignWidth="500">
    <Grid Background="White">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="2*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <Label Content="Nome:"  Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left" VerticalAlignment="Center" />
        <TextBox Grid.Column="1" Grid.Row="0"  Margin="3" TabIndex="0" Text="{Binding Pessoa.Nome, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        <Label Content="Sobrenome:"  Grid.Column="0" Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Center" />
        <TextBox Grid.Column="1" Grid.Row="1"  Margin="3" TabIndex="1" Text="{Binding Pessoa.Sobrenome, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        <Label Content="Última atualização:"  Grid.Column="0" Grid.Row="2" HorizontalAlignment="Left" VerticalAlignment="Center" />
        <Label Grid.Column="1" Grid.Row="2"  Margin="3" HorizontalAlignment="Left" Content="{Binding Pessoa.UltimaAtualizacao, Mode=TwoWay}" />
        <Button Content="Atualizar" Grid.Column="1" Grid.Row="3" Width="70" Margin="2,2,3,2" HorizontalAlignment="Right" Command="{Binding CommandAtualizar}" />
    </Grid>
</UserControl>

推荐答案

DelegateCommand.ObservesPropery不支持复杂的对象属性.它仅支持在命令定义的ViewModel上存在的属性.这是因为复杂对象的生命周期是未知的,并且如果创建了该对象的许多实例,则会导致内存泄漏.我的建议是像这样定义您的财产:

DelegateCommand.ObservesPropery doesn't support complex object properties. It only supports properties that exist on the ViewModel in the command is defined. This is because the lifecycle of complex objects are unknown, and a memory leak would be created if many instances of the object was created. My recommendation would be to define you property like this:

private Pessoa _pessoa;
public Pessoa Pessoa
{
    get { return _pessoa; }
    set 
    {
        if (_pessoa != null)
            _pessoa.PropertyChanged -= PropertyChanged; 

        SetProperty(ref _pessoa, value);


        if (_pessoa != null)
            _pessoa.PropertyChanged += PropertyChanged;
    }
}

然后在PropertyChanged方法中,调用DelegateCommand.RaiseCanExecuteChanged

Then in the PropertyChanged method, call DelegateCommand.RaiseCanExecuteChanged

现在,Prism中为Xamarin.Forms 7.0提供了复杂属性支持.

Complex property support is now available in Prism for Xamarin.Forms 7.0.

这篇关于在Prism 6处,ObservesProperty方法未观察模型的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆