zoukankan      html  css  js  c++  java
  • 在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
    {
        /// <summary>
        /// 业务实体(Business Entity)
        /// </summary>
        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
    {
        /// <summary>
        /// 视图模型:专门用来为界面(视图)来服务的,这里用来包含一些业务逻辑
        /// </summary>
        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();
                    });
                }
            }
    
            /// <summary>
            /// 使用命令的机制代替了事件
            /// </summary>
            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>
    
  • 相关阅读:
    D
    pat 甲级 1003 Emergency(最短路计数)
    Goldbach
    pta 1148 Werewolf
    CodeForces
    pta 1144 The Missing Number
    2020团体程序设计天梯赛 L1-3 洛希极限
    2020团体程序设计天梯赛 L1-2 猫是液体
    2020团体程序设计天梯赛 L1-1 嫑废话上代码
    2020年团体程序设计天梯赛-题解
  • 原文地址:https://www.cnblogs.com/chenxizhang/p/3281910.html
Copyright © 2011-2022 走看看