wpf Prism 6 DelegateCommand 观察属性代码

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33624193/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 13:31:39  来源:igfitidea点击:

Prism 6 DelegateCommand ObservesProperty code

c#wpfmvvmprism

提问by Neil

Hi Good day i'm just new with WPF and MVVM design pattern and i've learned a lot from the blogs and videos of sir BRIAN LAGUNAS in PRISM.. but just want to ask a noob question..whats wrong with my code it doest work for me... any help is very appreciated thanks. here's my code :

嗨,美好的一天,我只是 WPF 和 MVVM 设计模式的新手,我从 PRISM 中 BRIAN LAGUNAS 爵士的博客和视频中学到了很多东西。对我不起作用......非常感谢任何帮助。这是我的代码:

MY VIEW MODEL

我的视图模型

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

myModel

我的模型

Declared to another Class File

声明到另一个类文件

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

ViewXaml Code

查看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>

I've Already read this but it doesnt work for me.. and cant understand how can i properly code it.. please help me ragarding this matter ..HOPE for any reply soon..thx

我已经读过这个,但它对我不起作用..并且无法理解我如何正确编码它..请帮我讨论这个问题..希望尽快得到任何答复..thx

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

ObservesProperty 方法不在 Prism 6 观察模型的属性

采纳答案by galakt

1) You can`t use complex datamodel like you want, so try it

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) Change your constructor

2)改变你的构造函数

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

回答by Jens

First i have to say something about your naming. Name your Classes clear. Call your ViewModele.g. PersonViewModelor just ViewModelwhen your application is not that big and not Person, because Personis obviously the Model. Moreover myPErsonis a very bad name, because it is very similar to your other Personclass and you should PascalCaseyour class names.

首先我得说一下你的命名。清楚地命名你的班级。例如,或者在您的应用程序不是那么大时调用您的ViewModel,因为显然是Model。此外,这是一个非常糟糕的名称,因为它与您的其他类非常相似,您应该将类名PascalCasePersonViewModelViewModelPersonPersonmyPErsonPerson

Now to your code. I know nothing about Prismso my code depends on the MVVMpattern only without the support of the Prism Libraries.

现在到您的代码。我对此一无所知,Prism因此我的代码MVVM仅在没有棱镜库支持的情况下才依赖于模式。

First i want to change the ModelPerson. The class looks very easy in my code (just uses auto properties):

首先我想改变ModelPerson。这个类在我的代码中看起来很简单(只使用自动属性):

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

    public string LastName { get; set; }

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

The PersonViewModelis a littlebit more complex because it implements the INotifyPropertyChangedinterface. I am also using the very common RelayCommandwhich you can find in the link under the accepted answer.

PersonViewModel,因为它实现了一个littlebit更复杂的INotifyPropertyChanged界面。我还使用了非常常见的RelayCommand,您可以在已接受答案下的链接中找到它。

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

I cleared up your View a bit, because it is much shorter now. but all in all everything stayed the same. i just renamed the properties and stuff:

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

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

All in all i would recommend to you to use the common MVVM pattern without the Prism Library. When you understood MVVM good you still can go for Prism. Hope it helps.

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

回答by Winseral

View Xaml Code

查看 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"> 

You are missing the ViewModelLocator

您缺少 ViewModelLocator

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