【问题标题】:Prism 6 DelegateCommand ObservesProperty codePrism 6 DelegateCommand ObservesProperty code
【发布时间】:2015-11-10 06:33:29
【问题描述】:

嗨,美好的一天,我是 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; }
}

我的模型

声明到另一个类文件

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

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

【问题讨论】:

  • 按钮在做什么?
  • 发布消息框“HOLA”。
  • 好的。现在我看到了。代码有什么问题?您没有在 TextBoxes 中看到任何内容?
  • 它被绑定到一个 DelegateCommand 属性。它应该执行“执行”方法..但在它执行之前,按钮被禁用,直到两个文本框被填满,谢谢你评论@JensHorstmann
  • 它被绑定到一个 DelegateCommand 属性。它应该执行“执行”方法..但在它执行之前,按钮被禁用,直到两个文本框被填满......但在我的情况下它不起作用..谢谢你的评论@JensHorstmann

标签: c# wpf mvvm prism


【解决方案1】:

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

【讨论】:

  • @Neil 将此答案标记为解决方案,如果对您有帮助的话
【解决方案2】:

首先我要说一下你的命名。清楚地命名您的课程。调用您的 ViewModel 例如PersonViewModel 或只是 ViewModel 当您的应用程序不是那么大而不是 Person 时,因为 Person 显然是 Model。此外myPErson 是一个非常糟糕的名字,因为它与你的其他Person 类非常相似,你应该PascalCase 你的类名。

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

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

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,您可以在已接受答案下的链接中找到它。

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。 希望对您有所帮助。

【讨论】:

  • 感谢@Jens Horstmann 先生的建议……这将帮助我改进我的编码……出于好奇,我只想使用 PRISM 库并对其进行研究……我可以向您询问链接吗,书供我参考先生?为了将来的学习..请...非常感谢
  • @Neil 用你的链接做你想做的事=P
  • 哈哈.. 先生 ^_^.. 的任何建议链接供我将来参考先生.. 我正在学习.. 请... @Jens Horstmann
  • stackoverflow.com/questions/1405739/… 我想你可以自己google一下。我找不到我的教程。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-23
    • 2014-12-13
    • 2016-03-15
    • 2020-12-11
    • 2017-05-12
    • 2019-02-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多