Prism 6 DelegateCommand Observes属性代码

Prism 6 DelegateCommand ObservesProperty code

嗨,你好,我是 WPF 和 MVVM 设计模式的新手,我从 PRISM 的 BRIAN LAGUNAS 爵士的博客和视频中学到了很多东西..但只想问一个菜鸟问题..什么我的代码有问题,它对我有用……非常感谢任何帮助。 这是我的代码:

我的视图模型

public class Person : BindableBase
{
    private myPErson _MyPerson;
    public myPErson MyPerson
    {
        get { return _MyPerson; }
        set
        {
            SetProperty(ref _MyPerson, value);
        }
    }

    public Person()
    {
        _MyPerson = new myPErson();
        updateCommand = new DelegateCommand(Execute, CanExecute).ObservesProperty(() => MyPerson.FirstName).ObservesProperty(() => MyPerson.Lastname);

    //    updateCommand = new DelegateCommand(Execute).ObservesCanExecute((p) => CanExecute); /// JUST WANNA TRY THIS BUT DUNNO HOW
    }

    private bool CanExecute()
    {
        return !String.IsNullOrWhiteSpace(MyPerson.FirstName) && !String.IsNullOrWhiteSpace(MyPerson.Lastname);
    }

    private void Execute()
    {
        MessageBox.Show("HOLA");
    }

    public DelegateCommand updateCommand { get; set; }
}

我的模型

声明到另一个Class文件

public class myPErson : BindableBase
{
    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            SetProperty(ref _firstName, value);
        }
    }

    private string _lastname;
    public string Lastname
    {
        get { return _lastname; }
        set
        {
            SetProperty(ref _lastname, value);
        }
    }
}

查看 Xaml代码

<Window x:Class="Prism6Test.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:myVM="clr-namespace:Prism6Test.ViewModel"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <myVM:Person x:Key="mainVM"/>
    </Window.Resources>
<Grid DataContext="{StaticResource mainVM}">
        <TextBox HorizontalAlignment="Left" Height="23" Margin="217,103,0,0" TextWrapping="Wrap" Text="{Binding MyPerson.FirstName,UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Width="120"/>
        <TextBox HorizontalAlignment="Left" Height="23" Margin="217,131,0,0" TextWrapping="Wrap" Text="{Binding MyPerson.Lastname,UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Width="120"/>
        <Button Content="Button" Command="{Binding updateCommand}" HorizontalAlignment="Left" Margin="242,159,0,0" VerticalAlignment="Top" Width="75"/>

    </Grid>
</Window>

我已经读过这篇文章,但它对我不起作用..并且不明白我该如何正确编码..请帮我解决这个问题..希望尽快回复..thx

1) 你不能随心所欲地使用复杂的数据模型,所以试试吧

private myPErson _MyPerson;
    public myPErson MyPerson
    {
        get { return _MyPerson; }
        set
        {
            if (_MyPerson != null)
                _MyPerson.PropertyChanged -= MyPersonOnPropertyChanged;

            SetProperty(ref _MyPerson, value);


            if (_MyPerson != null)
                _MyPerson.PropertyChanged += MyPersonOnPropertyChanged;
        }
    }

    private void MyPersonOnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
    {
        updateCommand.RaiseCanExecuteChanged();
    }

2) 改变你的构造函数

public Person()
    {
        MyPerson = new myPErson();
        updateCommand = new DelegateCommand(Execute, CanExecute);
    }

首先我得说说你的命名。明确命名您的 类。调用您的 ViewModel 例如PersonViewModel 或者只是 ViewModel 当你的应用程序不是那么大而不是 Person,因为 Person 显然是 模型 。此外 myPErson 是一个非常糟糕的名字,因为它与你的其他 Person class 非常相似,你应该 PascalCase 你的 class 名字。

现在你的代码。我对 Prism 一无所知,所以我的代码仅在没有 Prism 库支持的情况下依赖于 MVVM 模式。

首先我想更改 模型 Person。 class 在我的代码中看起来非常简单(只使用自动属性):

public class Person
{
    public string FirstName { get; set; }

    public string LastName { get; set; }

    public Person()
    {
        this.LastName = string.Empty;
        this.FirstName = string.Empty;
    }
}

PersonViewModel 有点复杂,因为它实现了 INotifyPropertyChanged 接口。我还使用了非常常见的 RelayCommand,您可以在接受的答案下的 link 中找到它。

public class PersonViewModel : INotifyPropertyChanged
{
    private Person person;

    private ICommand updateCommand;

    public PersonViewModel()
    {
        this.Person = new Person();
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public Person Person
    {
        get
        {
            return this.person;
        }

        set
        {
            this.person = value;

            // if you use VS 2015 or / and C# 6 you also could use
            // this.OnPropertyChanged(nameof(Person));
            this.OnPropertyChanged("Person");
        }
    }

    public ICommand UpdateCommand
    {
        get
        {
            if (this.updateCommand == null)
            {
                this.updateCommand = new RelayCommand<Person>(this.OpenMessageBox, this.OpenMessageBoxCanExe);
            }

            return this.updateCommand;
        }
    }

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    private void OpenMessageBox(Person person)
    {
        MessageBox.Show("Hola");
    }

    private bool OpenMessageBoxCanExe(Person person)
    {
        if (person == null)
        {
            return false;
        }

        if (string.IsNullOrWhiteSpace(person.FirstName) || string.IsNullOrWhiteSpace(person.LastName))
        {
            return false;
        }

        return true;
    }
}

我稍微整理了一下你的视图,因为它现在短多了。但总而言之,一切都保持不变。我刚刚重命名了属性和内容:

<Window ...>
    <Window.Resources>
        <wpfTesst:PersonViewModel x:Key="ViewModel" />
    </Window.Resources>
    <Grid DataContext="{StaticResource ViewModel}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <TextBox Grid.Row="0" TextWrapping="Wrap" Text="{Binding Person.FirstName, UpdateSourceTrigger=PropertyChanged}" />
        <TextBox Grid.Row="1" TextWrapping="Wrap" Text="{Binding Person.LastName, UpdateSourceTrigger=PropertyChanged}" />
        <Button Grid.Row="2" Content="Button" Command="{Binding UpdateCommand}" CommandParameter="{Binding Person}"/>
    </Grid>
</Window>

总而言之,我建议您使用没有 Prism 库的通用 MVVM 模式。当你很好地理解 MVVM 时,你仍然可以选择 Prism。 希望对你有帮助。

查看Xaml代码

<Window x:Class="Prism6Test.Views.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:myVM="clr-namespace:Prism6Test.ViewModel"
    Title="MainWindow" Height="350" Width="525"> 

您缺少 ViewModelLocator

    xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
    prism:ViewModelLocator.AutowireViewModel="True"