近來練習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 = "[email protected]" };
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
裡面有SaveDataCommand用于模拟儲存指令,我希望使用者必須輸入了Person.Name Person.Email指令才能夠被執行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 }
-
建立View
View Code
我翻查了資料Prism下實作指令綁定主要有如下幾種方式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>
<!-- 借助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方式實際更靈活。
- 有知道的幫我解答下,謝謝
附件