WPFでMVVMを実装

WPF の基本と MVVM の実装方法を学ぶために、シンプルなプログラムを

書いてみました。下記のプログラムは「MainWindow.xaml」と「MainWindow.xaml.cs」が View 、「MainWindowViewModel.cs」が ViewModel、

「PersonModel.cs」が Model になっています。

 イメージ

f:id:azumal:20140413105656j:plain

 

MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:e="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="450" Width="915">
<Window.Resources>
<Style TargetType="{x:Type Label}">
<Setter Property="Width" Value="100"/>
<Setter Property="Margin" Value="5"/>
</Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Width" Value="150"/>
<Setter Property="Height" Value="30"/>
</Style>
<Style TargetType="{x:Type Calendar}">
<Setter Property="Width" Value="250"/>
<Setter Property="Height" Value="200"/>
</Style>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="Width" Value="150"/>
</Style>
<Style TargetType="{x:Type Button}" x:Key="ButtonStyle">
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="30"/>
<Setter Property="Margin" Value="10 0 10 0"/>
</Style>
<ObjectDataProvider x:Key="EnumSex" MethodName="GetValues" ObjectType="{x:Type e:Enum}">
<ObjectDataProvider.MethodParameters>
<x:TypeExtension TypeName="local:Sexes"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="450"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Padding="10">
<StackPanel>
<DockPanel>
<Label x:Name="IdLabel" Content="ID"/>
<TextBox x:Name="IdTextBox" >
<TextBox.Text>
<Binding Path="RegisteredPerson.PersonID">
<Binding.ValidationRules>
<DataErrorValidationRule></DataErrorValidationRule>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</DockPanel>
<DockPanel>
<Label x:Name="FirstNameLabel" Content="性"/>
<TextBox x:Name="FirstNameTextBox" Text="{Binding RegisteredPerson.FirstName}"/>
</DockPanel>
<DockPanel>
<Label x:Name="LastNameLabel" Content="名"/>
<TextBox x:Name="LastNameTextBox" Text="{Binding RegisteredPerson.LastName}"/>
</DockPanel>
<DockPanel>
<Label x:Name="RoleLabel" Content="性別"/>
<ComboBox ItemsSource="{Binding Source={StaticResource EnumSex}}" SelectedValue="{Binding RegisteredPerson.Sex}" Margin="5"/>
</DockPanel>
<DockPanel>
<Label x:Name="HireDateLabel" Content="誕生日"/>
<Calendar x:Name="HireDateCalender" SelectedDate="{Binding RegisteredPerson.HireDate}"/>
</DockPanel>
<DockPanel HorizontalAlignment="Right">
<Button x:Name="RegisterButton" Style="{StaticResource ButtonStyle}" Content="登録"
Command="{Binding RegisterPersonCommand}"
CommandParameter="{Binding RegisteredPerson}"/>
<Button x:Name="CancelButton" Style="{StaticResource ButtonStyle}" Content="キャンセル"
Command="{Binding CancelCommand}"
CommandParameter="{Binding RegisteredPerson}"/>
</DockPanel>
</StackPanel>
</Border>
<ListView Grid.Column="1" ItemsSource="{Binding People}">
<ListView.View>
<GridView>
<GridViewColumn Header="ID" DisplayMemberBinding="{Binding PersonID}" Width="50"/>
<GridViewColumn Header="性" DisplayMemberBinding="{Binding FirstName}" Width="100"/>
<GridViewColumn Header="名" DisplayMemberBinding="{Binding LastName}" Width="100"/>
<GridViewColumn Header="性別" DisplayMemberBinding="{Binding Sex}" Width="50"/>
<GridViewColumn Header="誕生日" DisplayMemberBinding="{Binding BirthDay, StringFormat=yyyy/MM/dd}" Width="120"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>

MainWindow.xaml.cs


using System.Windows;
namespace WpfApplication1 {
    public partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();
            this.DataContext = new MainWindowViewModel();
        }
    }
}

MainWindowViewModel.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections.ObjectModel;
using System.Windows.Input;

namespace WpfApplication1 {
    public class MainWindowViewModel {
        public Person RegisteredPerson { get; set; }
        public ObservableCollection<Person> People { get; set; }
        public ICommand RegisterPersonCommand { get; set; }
        public ICommand CancelCommand { get; set; }
        public List<Sexes> Roles { get; set; }

        public MainWindowViewModel() {
            People = new ObservableCollection<Person>();
            RegisteredPerson = new Person();
            RegisterPersonCommand = new RegisterPerson(this);
            CancelCommand = new Cancel(this);
        }
    }

    public class RegisterPerson : ICommand {
        private ObservableCollection<Person> _people;
        private Person _person;
        public RegisterPerson(MainWindowViewModel view) {
            _people = view.People;
            _person = view.RegisteredPerson;
        }

        public event EventHandler CanExecuteChanged;
        public bool CanExecute(object parameter) {
            return true;
        }

        public void Execute(object parameter) {
            var p = (Person)parameter;
            _people.Add(new Person(
                p.PersonID, p.FirstName, p.LastName, p.Sex, p.BirthDay));
            _person.PersonID++;
            _person.FirstName = string.Empty;
            _person.LastName = string.Empty;
            _person.Sex = Sexes.男性;
            _person.BirthDay = DateTime.Today;
        }
    }

    public class Cancel : ICommand {
        private ObservableCollection<Person> _people;
        public Cancel(MainWindowViewModel view) {
            _people = view.People;
        }

        public event EventHandler CanExecuteChanged;
        public bool CanExecute(object parameter) {
            return true;
        }

        public void Execute(object parameter) {
            var p = (Person)parameter;
            p.PersonID = _people.Max<Person>(u => u.PersonID) + 1;
            p.FirstName = string.Empty;
            p.LastName = string.Empty;
            p.Sex = Sexes.男性;
            p.BirthDay = DateTime.Today;
        }
    }
}

PersonModel.cs


using System;
using System.ComponentModel;

namespace WpfApplication1 {
    public class Person : INotifyPropertyChanged, IDataErrorInfo {
        public Person() {
            PersonID = 1;
            Sex = Sexes.男性;
            BirthDay = DateTime.Today;
        }

        public Person(int id, string firstName,
        string lastName, Sexes sex, DateTime birthDay) {
            PersonID = id;
            FirstName = firstName;
            LastName = lastName;
            Sex = sex;
            BirthDay = birthDay;
        }

        private int _personID;
        public int PersonID {
            get {
                return _personID;
            }
            set {
                if (_personID == value)
                    return;
                _personID = value;
                RaisePropertyChanged("PersonID");
            }
        }

        private string _firstName;
        public string FirstName {
            get {
                return _firstName;
            }
            set {
                if (_firstName == value)
                    return;
                _firstName = value;
                RaisePropertyChanged("FirstName");
            }
        }

        private string _lastName;
        public string LastName {
            get {
                return _lastName;
            }
            set {
                if (_lastName == value)
                    return;
                _lastName = value;
                RaisePropertyChanged("LastName");
            }
        }

        private Sexes _sex;
        public Sexes Sex {
            get {
                return _sex;
            }
            set {
                if (_sex == value)
                    return;
                _sex = value;
                RaisePropertyChanged("Sex");
            }
        }

        private DateTime _birthDay;
        public DateTime BirthDay {
            get {
                return _birthDay;
            }
            set {
                if (_birthDay == value)
                    return;
                _birthDay = value;
                RaisePropertyChanged("BirthDay");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void RaisePropertyChanged(string propertyName) {
            if (PropertyChanged != null)
                PropertyChanged(this,
                new PropertyChangedEventArgs(propertyName));

        }

        public string this[string propertyName] {
            get {
                if (propertyName == "PersonID") {
                    if (PersonID < 1)
                        return "IDは1以上の数値を入力してください。";
                }
                return null;
            }
        }

        public string Error {
            get {
                return null;
            }
        }
    }

    public enum Sexes {
        男性,
        女性
    }
}

仮想マシンにVMware Tools をインストールする

前回仮想マシン(CentOS)のインストールまで完了したので、仮想マシンVMware Tools をインストールしていきます。

 

まず、 vSphere Client の「インベントリ(N)」→「仮想マシン(V)」→「ゲスト(G)」→「VMware Tools のインストール/アップグレード(W)」をクリックします。

f:id:azumal:20140412232734j:plain

 

ゲストOS内でフォルダーが開くので、その中にある tar ボールを展開します。

f:id:azumal:20140412233113j:plain

 

展開したファイルの中から、「vmware-install.pl」を実行します。

表示されるダイアログでは「端末内で実行する(T)」を選択します。

f:id:azumal:20140412233255j:plain

以上でインストール終了です。

これで検証環境として使用できるはずです。

自分のPCでは検証環境として不十分な場合は、

http://labs.hol.vmware.com/

でトレーニングを受講できます。

勉強になりますので是非試してみてください。

VMware vSphere Hypervisor に仮想マシンをインストールする

VMware Player にインストールした VMware vSphere Hypervisor 上に仮想マシンをインストールする手順をまとめます。今回は CentOS の64ビットをインストールします。

 

1.「新規仮想マシンの作成」ダイアログを起動する

 vSphere Client でESXi ホストを右クリックし、「新規仮想マシン(N)...」をクリックします。

f:id:azumal:20140412092329j:plain

 

2.構成を決定する

 「標準」と「カスタム」があります。

 ここでは「標準」を選択します。

f:id:azumal:20140412092518j:plain

 

3.名前を指定する

 仮想マシン名を入力します。

f:id:azumal:20140412092726p:plain

 

4.ストレージ

 使用するストレージを選択します。

f:id:azumal:20140412092915j:plain

 

5.ゲストOSの種類を選択する

 今回は CentOS 64ビットなので「Linux」「CentOS 4/5/6(64 ビット)」を選択します。

f:id:azumal:20140412093217j:plain

 

6.ネットワーク構成を決定する

 ここはデフォルトにしておきます。

f:id:azumal:20140412093323j:plain

 

7.ディスクの作成

 ディスク容量に任意の値を入力します。 ディスク作成の形式は「Thin Provision」を選択します。

 この形式はファイル作成時に領域を確保しないため、短時間でディスクを作成できます。

f:id:azumal:20140412094132j:plain

 次の画面で「終了」を押せば完了です。

 

8.ISO イメージを選択する

 作成した仮想マシンを vSphere Client で選択し、パワーオンします。

 起動したらクライアントコンソールから「CD/DVDドライブ1」→「ローカル ディスクの ISO イメージに接続...」を選択します。

 ダイアログが開きますので、CentOS の ISO イメージを選択します。

f:id:azumal:20140412101518j:plain

 

9.仮想マシンを再起動する

 仮想マシンを再起動するために、「仮想マシン(V)」→「ゲスト(G)」→「Ctrl+Alt+Delete の送信(S)」をクリックします。

f:id:azumal:20140412101837j:plain

 

10.ゲスト OS インストール開始

 ここから CentOS のインストールが始まります。

f:id:azumal:20140412102121j:plain

OS のインストールが完了すれば、仮想環境のできあがりです!

あとは VMware Tools のインストールについてまとめようと思います。

 

VMware vSphere Client をインストールする

VMware vSphere Hypervisor をインストールした後、EXSi にアクセスするため

VMware vSphere Client をインストールします。

 

1.exe をダウンロードする

 ブラウザから「https//(ESXiのIPアドレス)/」にアクセスします。

 下記画像中央の「Download vSphere Client」をクリックするとexeを

 ダウンロードできます。

f:id:azumal:20140411235426p:plain

 

 

2.exe を実行する

 インストーラーの指示に従って進めばOKです。

 

3.ライセンスを適用する

 デスクトップにできたvSphere Client ショートカットを実行します。

f:id:azumal:20140412000427j:plain

 

 

「構成」タブ→「ライセンス機能」→「編集」をクリックします。

f:id:azumal:20140412000943j:plain

 

 

 

https://my.vmware.com/jp/group/vmware/evalcenter?p=free-esxi5&lp=default」で

取得したライセンスを入力します。

 

f:id:azumal:20140412002345j:plain

 

こんな感じでVMware vSphere Hypervisor を使用できるようになります。

 

VMware vSphere Hypervisor を VMware Player にインストール

VMware vSphere Hypervisor とは VMware 社から無償で提供されている仮想化ソフトウェアです。ディスクやストレージにインストールすることで複数のOSを VMware Hypervisor上で動作させることができます。ここでは検証用として、同じくVMware 社から無償提供されているVMware Player にVMware Hypervisorをインストールします。

 

1.VMware のサイトでアカウントを作成する

 https://my.vmware.com/jp/web/vmware/evalcenter?p=free-esxi5&lp=default

 上記アドレスにアクセスし、アカウントを作成します。

 

2.VMware vSphere Hypervisor をのライセンスを発行する

 アカウント作成が完了したら、「ライセンスとダウンロード」タブでライセンスキーを取得します。

 

3.VMware vSphere Hypervisor をダウンロードする

 「ダウンロードマネージャの起動」からISOイメージをダウンロードします。

 

4.VMware Player に VMware vSphere Hypervisor をインストールする

 「新規仮想マシンの作成」→「インストーラディスクイメージファイル」でダウンロードしたISOファイルを選択します。インストール開始後は「Enter」と「F11」で進めます。

f:id:azumal:20140410223532j:plain

 

 

5.インストールディスクと言語を選択する

f:id:azumal:20140410223912p:plain

 

f:id:azumal:20140410224012j:plain

 

 

6.システムの設定をする

 インストール完了後、再起動します。

 再起動後「F2」→設定したrootのパスワードを入力します。

f:id:azumal:20140410224513j:plain

 

ネットワーク設定等が完了したら使用可能になります。

VMware vSphere Client のインストールや仮想マシンのインストールはまた今度書きます。

「1ヶ月おき」は隔月?毎月?

先日、プログラム仕様書に「1ヶ月おき」と書くと、読み手によって解釈が異なる場合があるため使用すべきでないとの話を聞きました。

 

その解釈には以下の2通りです。

1.隔月

2.毎月

 

ちなみに私は「2.毎月」派です。

 

ちょっと気になったため辞書やネットで調べてみましたが、明確に

記載されているものはありませんでした。

その後しばらく頭の中で考えたところ、私としては「両方正しい」との結論に至りました。

その理由は以下のとおりです。

1.隔月

 「1ヶ月」を整数値(離散値)と捉えた場合。

 これは人を1列に並べて「1人おき」と表現した場合と同じです。

2.毎月

 「1ヶ月」を連続した値と捉えた場合。

 1ヶ月=30日=720時間=43200分=2592000秒 であるため、

 「1ヶ月おき」も「2592000秒おき」も同じがいいよね ということです。

 言い換えれば「1ヶ月という期間おいた後」です。

 

連続した値を持つものに対して「おき」は使用しない方がよいですね。

 

※日本語の専門家でもない一般人の私見です。