在WPF应用程序中利用IEditableObject接口实现可撤销编辑的对象
2021-02-09 15:14
在WPF应用程序中利用IEditableObject接口实现可撤销编辑的对象
这是我辅导的一个项目开发中的例子,他们是用WPF做界面开发,在学习了如何使用MVVM来实现界面与逻辑的分离,并且很好的数据更新之后,有一个疑问就是,这种双向的数据更新确实很不错,但如果我们希望用户可以撤销修改怎么办呢?其实这个功能,很早就有,甚至在原先的Windows Forms里面也可以实现。秘密就是实现IEditableObject这个接口。
关于这个接口的官方文档在这里:http://msdn.microsoft.com/zh-cn/library/vstudio/system.componentmodel.ieditableobject.aspx
我做了一个小的例子,帮助大家来理解。该例子使用了MVVM这种设计模式,如果你对此不熟悉,请先参考:http://www.cnblogs.com/chenxizhang/archive/2011/10/01/2197786.html
这个例子,你可以通过 http://files.cnblogs.com/chenxizhang/WpfApplicationBindingSample.zip 进行下载
Model:Employee
using System.ComponentModel; namespace WpfApplicationBindingSample.Models { ////// 业务实体(Business Entity) /// class Employee : INotifyPropertyChanged,IEditableObject { private string _firstName; public string FirstName { get { return _firstName; } set { if (_firstName != value) { _firstName = value; if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("FirstName")); PropertyChanged(this, new PropertyChangedEventArgs("FullName")); } } } } private string _lastName; public string LastName { get { return _lastName; } set { if (_lastName != value) { _lastName = value; if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("LastName")); PropertyChanged(this, new PropertyChangedEventArgs("FullName")); } } } } public string FullName { get { return FirstName + "," + LastName; } } public event PropertyChangedEventHandler PropertyChanged; private Employee backup;//用这个字段来保存一个备份数据 public void BeginEdit() { //开始编辑,此时将当前的状态保存起来,以便后续可以根据情况提交或者撤销更改 backup = this.MemberwiseClone() as Employee;//通过克隆的方式直接地复制一份数据 } public void CancelEdit() { //撤销编辑,此时将对象状态恢复到备份的状态 this.FirstName = backup.FirstName; this.LastName = backup.LastName; } public void EndEdit() { //结束编辑,这里可以不做任何事情,也可以添加一些额外的逻辑 } } }
ViewModel:
using GalaSoft.MvvmLight; using GalaSoft.MvvmLight.Command; using System.Windows; using WpfApplicationBindingSample.Models; namespace WpfApplicationBindingSample.ViewModels { ////// 视图模型:专门用来为界面(视图)来服务的,这里用来包含一些业务逻辑 /// class MainWindowViewModel : ViewModelBase { public MainWindowViewModel() { CurrentEmployee = new Employee() { FirstName = "ares", LastName = "chen" }; } public Employee CurrentEmployee { get; set; } public RelayCommand EditCommand { get { return new RelayCommand(() => { //将该员工设置为开始编辑 CurrentEmployee.BeginEdit(); }); } } /// /// 使用命令的机制代替了事件 /// public RelayCommand SubmitCommand { get {//使用匿名方法 return new RelayCommand(() => { //结束编辑,让更改生效 CurrentEmployee.EndEdit(); MessageBox.Show(CurrentEmployee.FullName); }); } } public RelayCommand CancelCommand { get { return new RelayCommand(() => { CurrentEmployee.CancelEdit();//取消编辑,此时可以看到FullName那个标签的文本恢复到原来的值 }); } } } }
View:
Window x:Class="WpfApplicationBindingSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:WpfApplicationBindingSample.ViewModels"
Title="MainWindow"
Height="350"
Width="525">
Window.DataContext>
vm:MainWindowViewModel>vm:MainWindowViewModel>
Window.DataContext>
Window.Resources>
Style TargetType="TextBlock">
Setter Property="Margin"
Value="3">Setter>
Style>
Style TargetType="TextBox">
Setter Property="Width"
Value="200">Setter>
Setter Property="HorizontalAlignment"
Value="Left">Setter>
Style>
Style TargetType="Button">
Setter Property="Width"
Value="100">Setter>
Setter Property="HorizontalAlignment"
Value="Left">Setter>
Style>
Window.Resources>
StackPanel Margin="10">
TextBlock FontSize="30"
Text="编辑员工">TextBlock>
TextBlock Text="姓氏">TextBlock>
TextBox Text="{Binding CurrentEmployee.FirstName,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">TextBox>
TextBlock Text="名称">TextBlock>
TextBox Text="{Binding CurrentEmployee.LastName,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">TextBox>
TextBlock Text="全称">TextBlock>
TextBlock Text="{Binding CurrentEmployee.FullName}">TextBlock>
Button Content="编辑"
Command="{Binding EditCommand}">Button>
Button Content="提交"
Command="{Binding SubmitCommand}">Button>
Button Content="取消"
Command="{Binding CancelCommand}">Button>
StackPanel>
Window>
文章标题:在WPF应用程序中利用IEditableObject接口实现可撤销编辑的对象
文章链接:http://soscw.com/essay/53139.html