• [Prism练习] Prism下MVVM中命令绑定的CanExecute问题


    近来练习Prsim下实现MVVM的方式。

    找到Command绑定有点问题,想拿出来讨论下。

    比如,一个新增资料的界面中,我想:用户必须将所有应填写的数据项填写完毕后提交按钮才可用。

    于是我们开始劵起袖子


    •  建立WPF项目,NuGet添加对Prism的引用,创建相关文件夹
    • 建立一个简单的model和service
    View Code
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 
     6 namespace MvvmDemo2.Models
     7 {
     8     public class Person
     9     {
    10         public string Name { get; set; }
    11         public string Email { get; set; }
    12 
    13         public bool Validate() 
    14         {
    15             if (string.IsNullOrEmpty(this.Name) || string.IsNullOrEmpty(this.Email))
    16             {
    17                 return false;
    18             }
    19             else 
    20             {
    21                 return true;
    22             }
    23         }
    24     }
    25 }
    View Code
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 
     6 namespace MvvmDemo2.Models
     7 {
     8     public  class PersonService
     9     {
    10         public Person GetPerson() 
    11         {
    12             return new Person { Name = "坑定", Email = "sdj@163.com" };
    13         }
    14 
    15         public Person CreatePerson() 
    16         {
    17             return new Person();
    18         }
    19 
    20         public void Save(Person person) 
    21         {
    22             //TODO....
    23         }
    24     }
    25 }
    • 建立ViewModel
      View Code
       1 using System;
       2 using System.Collections.Generic;
       3 using System.Linq;
       4 using System.Text;
       5 
       6 using Microsoft.Practices.Prism.Commands;
       7 using Microsoft.Practices.Prism.ViewModel;
       8 
       9 using MvvmDemo2.Models;
      10 
      11 namespace MvvmDemo2.ViewModels
      12 {
      13     public class PersonViewModel:NotificationObject
      14     {
      15         private PersonService svc;
      16 
      17         public PersonViewModel()
      18         {
      19             this.svc = new PersonService();
      20             this.Person = svc.CreatePerson();
      21             this.SaveDataCommand = new DelegateCommand<Person>(SaveData, CanSaveData);
      22         }
      23 
      24         private Person person;
      25         public Person Person 
      26         {
      27             get 
      28             { 
      29                 return person; 
      30             }
      31             set 
      32             { 
      33                 person = value;
      34                 RaisePropertyChanged("Person");
      35             }
      36         }
      37 
      38         public string PersonName 
      39         {
      40             get { return this.Person.Name; }
      41             set 
      42             { 
      43                 this.Person.Name = value;
      44                 RaisePropertyChanged("PersonName");
      45                 //RaiseCanSaveDataChanged();
      46             }
      47         }
      48 
      49         public string PersonEmail 
      50         {
      51             get { return this.Person.Email; } 
      52             set 
      53             {
      54                 this.Person.Email = value;
      55                 RaisePropertyChanged("PersonEmail");
      56                 //RaiseCanSaveDataChanged();
      57             }
      58         }
      59 
      60         public DelegateCommand<Person> SaveDataCommand { get; set; }
      61 
      62         public void SaveData(Person person) 
      63         {
      64             this.svc.Save(person);
      65         }
      66 
      67         public bool CanSaveData(Person person) 
      68         {
      69             if (person == null)
      70             {
      71                 return false;
      72             }
      73             else 
      74             {
      75                 bool isValid = person.Validate();
      76                 return isValid;
      77             }
      78         }
      79 
      80         private void RaiseCanSaveDataChanged()
      81         {
      82             //DelegateCommand<Person> cmd = this.SaveDataCommand as DelegateCommand<Person>;
      83             //cmd.RaiseCanExecuteChanged();
      84             this.SaveDataCommand.RaiseCanExecuteChanged();
      85            
      86         }
      87 
      88         
      89     }
      90 }

      里面有SaveDataCommand用于模拟保存命令,我希望用户必须输入了Person.Name Person.Email命令才能够被执行

    • 建立View
      View Code
       1 <Window x:Class="MvvmDemo2.Views.PersonViewModel"
       2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       4         xmlns:vm="clr-namespace:MvvmDemo2.ViewModels"
       5         xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
       6         xmlns:ie="http://schemas.microsoft.com/expression/2010/interactions"
       7         xmlns:cmd="clr-namespace:Microsoft.Practices.Prism.Commands;assembly=Microsoft.Practices.Prism"
       8         Title="PersonViewModel" Height="300" Width="300">
       9     <Window.DataContext>
      10         <vm:PersonViewModel></vm:PersonViewModel>
      11     </Window.DataContext>
      12     <Window.Resources>
      13         <Style x:Key="TextBlockStyle" TargetType="TextBlock">
      14             <Setter Property="Padding" Value="5"></Setter>
      15             <Setter Property="Background" Value="AliceBlue"></Setter>
      16             <Setter Property="Foreground" Value="Blue"></Setter>
      17         </Style>
      18         <Style  TargetType="StackPanel">
      19             <Setter Property="Background" Value="#FFFFF0"></Setter>
      20         </Style>
      21         <Style x:Key="TextBoxStyle" TargetType="TextBox">
      22             <Setter Property="Margin" Value="5"></Setter>
      23             <Setter Property="Background" Value="WhiteSmoke"></Setter>
      24             <Setter Property="Foreground" Value="Black"></Setter>
      25             <Setter Property="BorderBrush" Value="Blue"></Setter>
      26         </Style>
      27     </Window.Resources>
      28     <StackPanel>
      29         <TextBlock Text="姓名:" Style="{StaticResource TextBlockStyle}" ></TextBlock>
      30         <TextBox  Style="{StaticResource TextBoxStyle}" Text="{Binding PersonName}"></TextBox>
      31         <TextBlock Text="Email:" Style="{StaticResource TextBlockStyle}"></TextBlock>
      32         <TextBox  Style="{StaticResource TextBoxStyle}"  Text="{Binding PersonEmail}"></TextBox>
      33         
      34         <Button Content="添加B" Margin="5" IsEnabled="{Binding CanSaveData}">
      35             <i:Interaction.Triggers>
      36                     <i:EventTrigger EventName="Click">
      37                         <i:InvokeCommandAction Command="{Binding SaveDataCommand}" CommandParameter="{Binding Person}"></i:InvokeCommandAction>
      38                 </i:EventTrigger>
      39             </i:Interaction.Triggers>
      40         </Button>
      41 
      42         <Button  Content="添加A" Margin="5" 
      43                     cmd:Click.Command="{Binding SaveDataCommand}"
      44                     cmd:Click.CommandParameter="{Binding Person}"></Button>
      45 
      46         <Button Content="添加C" Margin="5" Command="{Binding SaveDataCommand}" CommandParameter="{Binding Person}"/>
      47 
      48     </StackPanel>
      49 </Window>

      我翻查了资料Prism下实现命令绑定主要有如下几种方式

              <!-- 借助Blend -->
              <Button Content="添加B" Margin="5" IsEnabled="{Binding CanSaveData}">
                  <i:Interaction.Triggers>
                          <i:EventTrigger EventName="Click">
                              <i:InvokeCommandAction Command="{Binding SaveDataCommand}" CommandParameter="{Binding Person}"></i:InvokeCommandAction>
                      </i:EventTrigger>
                  </i:Interaction.Triggers>
              </Button>
              <!--Prism 命令-->
              <Button  Content="添加A" Margin="5" 
                          cmd:Click.Command="{Binding SaveDataCommand}"
                          cmd:Click.CommandParameter="{Binding Person}"></Button>
              <!--普通命令-->
              <Button Content="添加C" Margin="5" Command="{Binding SaveDataCommand}" CommandParameter="{Binding Person}"/>
    •  看看运行效果



      可见不管是否输入了系统要求完整信息提几种交按钮的状态都没有起变化;

    • 很疑惑,带着问题去找解答发现在Stack Overflow有人提出类似的问题

    • 回来修改了下代码 ViewModel代码
              public string PersonName 
              {
                  get { return this.Person.Name; }
                  set 
                  { 
                      this.Person.Name = value;
                      RaisePropertyChanged("PersonName");
                      RaiseCanSaveDataChanged();
                  }
              }
      
              public string PersonEmail 
              {
                  get { return this.Person.Email; } 
                  set 
                  {
                      this.Person.Email = value;
                      RaisePropertyChanged("PersonEmail");
                      RaiseCanSaveDataChanged();
                  }
              }
              private void RaiseCanSaveDataChanged()
              {
                  //DelegateCommand<Person> cmd = this.SaveDataCommand as DelegateCommand<Person>;
                  //cmd.RaiseCanExecuteChanged();
                  this.SaveDataCommand.RaiseCanExecuteChanged();
                 
              }

      这下按钮 A、C 有了效果

      按钮B仍然没有效果,B后台逻辑是是OK的,只是显示状态有问题,是不是Blend,Prism两家有些恩怨.... -.-!
      鉴于前面的添加了一些代码有些不爽的感觉,于是我想B方式可变通,而且B方式实际更灵活。

    • 有知道的帮我解答下,谢谢

     附件

  • 相关阅读:
    luogu P1768 天路
    [NOIP2008]双栈排序
    逆元板子集
    [NOIP2015]子串
    [USACO17JAN]Subsequence Reversal
    [NOIP2011] 聪明的质监员
    POJ2987 Firing
    2018.10.20模拟总结
    POJ3469 Dual Core CPU
    真实道路中,如何倒车、侧方停车 哪里是圆心就往哪边大方向 倒车实际是以圆心 画圆后轮进库看左右镜子 别剐蹭
  • 原文地址:https://www.cnblogs.com/bikaqiou2000/p/3062047.html
Copyright © 2020-2023  润新知