WPFアプリケーションでIEditableObjectインタフェースを使用して編集を取り消すことができるオブジェクトを実現

17402 ワード

これは私が指導したプロジェクト開発の例です.彼らは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()
        {
            //    ,          ,            
        }
    }
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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              
                });
            }
        }
    }
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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>