Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
436 views
in Technique[技术] by (71.8m points)

c# - ObservesProperty method isn't observing model's properties at Prism 6

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.

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...

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>
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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

Then in the PropertyChanged method, call DelegateCommand.RaiseCanExecuteChanged

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...