在WPF应用程序中利用IEditableObject接口实现可撤销编辑的对象

2021-02-09 15:14

阅读:435

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

 


评论


亲,登录后才可以留言!