プログラミングと日々思ったことなど

ブログ名通りです。仕事でプログラミングをはじめました。

オブジェクト指向プログラミングについて

オブジェクト指向プログラミング(Object Oriented Programming = OOP)とは
プログラムを書く人自身が、プログラムを把握しきれなくなることを防ぐためのプログラム設計方法です。

このプログラム設計方法の特徴は、3つあります。
カプセル化
 フィールドへの読み書きやメソッドの呼び出しを制限します。
 制限することによって、重要(プログラム中で、書き換えてはいけないもの)な情報(フィールド)や操作(メソッド)を保護することができます。
 これは誤りの起きにくいプログラム、つまりはクラスを設計する時に役立ちます。

②継承
 新しいクラスを作るとき、そのクラスがすでに作られているクラスと類似している部分がある場合があります。

 例)
 車の設計が書かれたクラスがもともとあって、新しくスポーツカーの設計を書く必要がある。

 そのときに、すでに作られたクラスのメンバ変数・メソッドを受け継ぐ仕組みです。
 もともとあったクラスは、基本クラスや親クラスと言います。
 新しく作るクラスを、派生クラスや子クラスと言います。

③多様性(ポリモーフィズム
 メソッドに多様な振る舞いをさせることです。
 多様な振る舞いをさせるメソッドは、抽象的になります。
 抽象的になるというのは、簡単に言えば(おそらく)「5m動く」を「動く」にする、ということです。
 「動く」にすると、各クラス内で何メートル動くのかを決めることができます。
 そうすることによって、効率的にプログラム開発を行えます。


今はこれが限界です。
1年後、詳しく書けるように頑張ろう。

DataGridの必須入力チェック【WPF】

今週も頑張りました。
オブジェクト指向の前に、昨日の復習を記事にします(難しかった・・・)

昨日会社で教えてもらったのは、DataGridの必須入力チェックです。
DataGridに表示されているデータを編集したとき、必須項目が未入力だった際にその項目の枠が赤くなり、かつ、「必須エラーです」とメッセージが表示される処理です。

この必須入力チェックは、登録ボタン(コマンド)を押すと処理されます。
まずコマンド内でどの項目がエラーなのか判別処理・表示文章設定します。
その後ViewのTargetUpdated内で、実際にエラーメッセージが表示されるように処理していきました。


DataGridViewModel.cs
//このbtnRegist_Clickは、登録ボタンのコマンドに仕込んであるもの。
public void btnRegist_Click()
{
	bool isError = this.DtoCheck();

	//チェック処理
	if(isError)
	{
		this.RaisePropertyChanged("Views");
		return;
	}

	if(MessageBoxResult.Yes == System.Windows.MessageBox.Show("変更項目を登録しますか?","登録変更確認",MessageBoxButton.YesNo))
	{
		testDataGridModel model =
			new testDataGridModel(this.Dto);
		model.InsertData(updateflag);

		//登録変更が成功したか

		isSuccess = model.IsSuccess;
		if(isSuccess)
		{
			//略...登録更新の成功・失敗メッセージ処理...
		}
	}
}

private bool DtoCheck()
{
	bool isError = false;
	//エラーフィールドのクリア
	//ここで中身をクリアにしておかないと、連続処理したときに前の処理が残ってしまう。
	foreach(DataRow dr in this.Dto.testData.Rows)
	{
		dr["ERROR_FIELD"] = string.Empty;
		dr["ERROR_MSG"] = string.Empty;
		dr.ClearErrors();
	}

        //foreachの中にforeachでRowとColumnを1つずつ取り出している(結果1つのCellずつ処理ができる)
	foreach(DataRow dr in this.dto.testData.Rows)
	{
		//testDataの列を一列ずつ読み込む
		foreach(DtaColumn dc in this.dto.testData.Columns)
		{
			//必須か選択項目か確認 
			if(sentakuFields(dc.ColumnName))
			{
				continue;
			}

			if((dr[dc.ColumnName] == null) || (dr[dc.ColumnName].Tostring() == string.Empty))
			{
				//ここで空のERROR_FIELD行の中身を作っている
				if(dr["ERROR_FIELD"].Tostring() == string.Empty)
				{
					dr["ERROR_FIELD"] = dc.ColumnName;
				}
				else
				{
					dr["ERROR_FIELD"] += " " + dc.ColumnName; //区切り指定
				}

				dr["ERROR_MSG"] = dc.ColumnName + "で必須エラーです。¥r¥n";
				dr.RowError = dc.ColumnName + "で必須エラーです。¥r¥n";
				dr.SetColumnError(dc,dr["ERROR_MSG"].Tostring());

				isError = true;
			}
		}
	}
	return isError;

}

//選択項目を、ここで抜き出し
private bool sentakuFields(string strFieldName)
{
	bool isSentaku = false;

	switch(strFieldName)
	{
		case "aa":
		case "bb":

		isSentaku = true;
		break;
	}

	return isSentaku;
}
	
DataGrid.cs(View)
public test()

{
	InitializeComponent();

	//画面が表示されたときに、色々なデータを取得する処理
	ThisForm = ExPageParamsUtil.GetPageParams("TForms") as ExMenuWindow;
	//...略

	this.DataContext =
		new testViewModel(CommonTbls,exWin,cmbAuth);
	this.testDataGrid.TargetUpdated += 
	new EventHandler<DataTransferEventArgs>(testDataGrid_TargetUpdated);

}

private void testDataGrid_TargetUpdated(object sender,DataTransferEventArgs e)
{
	//エラー内容のクリア
	for(int idx = 0;idx < this.testDataGrid.Rows.Count;idx++)
	{
		this.testDataGrid.Rows[idx].Errors.Clear();
	}

	BindingListCollectionView chkView =
		this.testDataGrid.ItemSorce as BindingListCollectionView;

	//フィルタかける前のすべてのデータを取得する。
	DataTable dt = ((DataView)chkView.SorceCollection).ToTable().Copy();

	//フィルタ圧縮かける <>''←これは値が入っているかどうかを判断することができる。
        //RowFiletrで圧縮をかけると、番号がおかしくなるので注意。
	DataRow[] drs = dt.Select("ERROR_FIELD<>''");

	foreach(DataRow dr in drs)
	{
		//エラー項目及びエラー内容の取得
		DataGridRowError dgErr = new DataGridRowError();
		string[] errField = dr["ERROR_FIELD"].Tostring().Split('');

		foreach(string fld in errField)
		{
			dgErr.ColumnsNames.Add(fld);
			dgErr.Message = dr.GetColumnError(fld);

			//エラーオブジェクトを対象データグリッド行にセットする

			//エラー行番号の取得
			int intRowIdx = dt.Rows.IndexOf(dr);
			//データグリッドエラー対象行にエラーセット
			this.testDataGrid.Rows[intRowIdx].Errors.Add(dgErr);
		}
	}
}

以上なのですが、このコードだとセレクターにメッセージが表示されません。
どうすれば良いのか、調べてみようと思います。


-----ここから雑記

教えてもらっていたのに、復習してみるとわかっていないところが出てきました。
書いてみるとわかっていないところがわかるので、これからもコードを書いていこうと思います。

あと、色々コードを教えてもらっていて思っていたことを、昨日やっと聞くことができました。
foreachの中に、foreachやifが入っているのが変な感じがしていたのですが、それは処理が多くなりそうであれば、別のメソッドへ飛ばしても良いそうです。

些細なことも答えてくれる先輩方が、会社にたくさんいるのがとてもありがたいです。

そういやボーナスは出るのかなー。
出たらマイコンキットか、Windowsを購入したいのです・・・うーん難しいかな・・・。

Listでコンボボックスの項目を追加する(グリッドコントロール)

朝早く起きてしまったので、昨日の復習を書きます。

昨日はC1.WPF.DataGridのテキストボックス列(デフォルト)からコンボボックス列へ変更する処理をしました。
以下はそのコードです。

 private void c1DataGrid_AutoGeneratingColumns(object sender, C1.WPF.DataGrid.DataGridAutoGeneratingColumnsEventArgs e)
    {
        if(e.Property.Name == "aaaa")
        {
        //コンボボックス設定
        var cmbClmn = new C1.WPF.DataGrid.DataGridComboBoxColumn(e.Property);
        cmbClmn.DisplayMemberPath = "a.NAME";
        cmbClmn.SelectedValuePath = "a.CODE";

        DataView dv = new DataView(this.aTbls.Tables["a.CODE"]);
        dv.RowFilter = "a.CODE.ccc = '00'";

        DataTable dtCode = dv.ToTable();

        List<Model> models = new List<Model>();
        foreach(DataRow dr in dtCode.Rows)
        {
            Model data = new Model();
            data.a.NAME = dr["a.CODE"].ToString() + " " + dr["a.NEME"].ToString();
            data.a.CODE = dr["a.CODE"].ToString();
            models.Add(data);
        }

        Model data1 = new Model();
        data1.a.NAME = "00 その他";
        data1.a.CODE = "00";
        models.Add(data1);

            cmbClmn.ItemSource = models;
        }

        if(e.Property.Name == "bbbb")
        {
            var cmbClmn = new C1.WPF.DataGrid.DataGridComboBoxColumn(e.Property);
            cmbClmn.DisplayMemberPath = "a.NAME";
            cmbClmn.SelectedValuePath = "a.CODE";

            List<Model> models = new List<Model>();

            Model data1 = new Model();
            data1.a.NAME = "00 選択";
            data1.a.CODE = "00";
            models.Add(data1);

            cmbClmn.ItemSource = models;

        }
  

Listは別クラスにてModelの箱(a.NAMEと、a.CODEのプロパティと、WPFなのでプロパティチェンジを記述)を作成しています。

if文が2つあるのですが、Gridのヘッダー名で違った項目を表示することができるようにするためです。
1つ目のif文の中には、ループ文があります。
これは、もともとデータベースにあった項目を使用しているためです。
直接データベースからは持ってこれないので、
DataView dv = new DataView(this.aTbls.Tables["a.CODE"]); ←ここ
にて、DataViewの中身を指定したのちにフィルターをかけて使用する項目を指定しています。

2つ目はもともとある項目を使用していないので、新しい項目だけを追加しています。


また、デフォルトのテキストボックスだった時、各テキストボックスのデータは数字で表示されるようになっていました。
それはDtoから取得してきたデータが、数字であるためです。
それをこの処理をすることによって、数字の意味に適応した文字に変更しています。
変更したのは、数字だと何を意味しているのかわかりづらいからです。

以上です。

昨日はまだよくわかっていないListと、DataViewが作業で出てきました。
これで少し整理できてよかったです。

SQLクエリ実行処理など

今週も色々苦戦していました。
中でもSQL関係が気になったので、その復習です。

DaoBase(親クラス...多分)にコーディングされている実行処理の中で、SQL実行処理クエリがありました。

DaoBase.cs

//機能名称 SQLクエリ実行処理
//パラメータで受け取ったSQL文を実行し、結果セット

//SQL条件パラメータ
protected DataTable ExecuteQuery(string sSql, IDbDataParameter[] collection, string tblName)
{
       try {
       	  DataSet ds = new DataSet();

       	  connection = DbFactory.GetCommand(sSql,connection)
       	  comm.Parameters.Clear();
       	  if(conParams.Driver == "ORACLE")
       	  {
       	  	foreach(OracleParameter p in collection)
       	  	{
       	  	  comm.Parameters.Add(p);
       	  	}
       	  }else
       	  {     //ココの処理がよくわからない明日聞く
      // 5.16 ifの条件、DriverでORACLEかSqlserverか切り替えていた。
     //が、何らかの理由でその必要がなくなったため、この部分が残った(今ココは通りません)
       	  	foreach(OracleParameter p in collection)
       	  	{
       	  		comm.Parameters.Add(p);
       	  	}
       	  }
       	  log.Debug(comm.CommandText);
       	  //アダプタ作成
       	  adapter = DbFactory.CreateAdapter(comm);
       	  adapter.Fill(ds);
       	  ds.Tables[0].TableName = tblName;
       	  return ds.Tables[0];
       }
     catch(Exception ex)
     {
    	log.Info("SQLクエリ実行時エラー",ex);
    	return new DataTable();
     }
     finally
     {
    	DbFactory.ReleaseConnection(connection);
     }
   	}
}

これによって、子クラスのSQLクエリも実行されるようになります。

またconnectionは、web.config内でパラメータが定義されています。

<add key="DRIVER" value="ORACLE" />
<add key="ConnectionCnt" value="2" />

valueが2なので、connectionが2より多く繋がれると、エラーが発生します。

そうして、DaoBaseにてクエリ実行処理がコーディングされていることによって、実行できるのが以下の情報取得処理です。

namespace Logic
{
	public class DaoImpl:DaoBase,IDaoaa
	{
		readonly log4net.Ilog log =
					log4net.LogManager.GetLogger
					 (System.Reflaction.MethodBase.GetCurrentMethod().DeclaringType);
		 public DaoImpl()
		  :base()
		  {

		  }
		  //情報取得処理
		 public DtoaaList GetDtoList(DtoaaList dto)
		 {
		 	string sSql = string.Empty;
		 	sSql = @"
		 		SELECT
		 			aa
		 			,bb
		 			,cc
		 			,...略
		 		FROM aa_COLUMNS
		 		ORDER BY aa,bb
		 	";
		  try
		  {
		  	DataTable dt = ExecuteQuery(sSql,"aa_COLUMNS");
		  	dto.Merge(dt,true,MissingSchemeAction.Ignore);
		  }
		  catch(Exception ex)
		  {
		  	log.Error("テーブル情報取得エラー",ex);
		  }
		  return dto;
		 }
	}
}

この処理で、データをDtoから取ってきています。
なので、同じDaoの中でセレクト文を作成するときにはconnectionは使用しなくて良いのです。

ちなみにこの中でLIKE文を使用するときには、||で%を囲わなければ文字だと判別してくれないようです。


-----ここから雑記
このconnectionの話を以前にもしていただいたのに、忘れてしまっていて再度教えてもらいました。
ぬおー悔しい。

そして現在、その悔しさをバネにしつつこの参考書を使って自習してます。

www.amazon.co.jp


この参考書は、綺麗なコードになるまでを詳しく書いてくれているのでわかりやすいです。
わかりやすいといっても、実際にコーディングしながら進めているので数ページ読むのに随分時間がかかってしまいますが…。



今回は以上です。
来週はオブジェクト指向について、今ある知識で頑張って書いていきます。

SQLについて色々【メモ】

Execute Query

DataContextクラスのメソッド。
SQLクエリを直接記述して、実行することができます。

クエリを直接記述したとき

(テーブル項目)
   ↓
(値:@をつける)
   ↓
(パラメータ:@をつける)

@がキーワードとなって、値を取得します。

*クエリを書くときは、カンマを前に書いた方が良い。


サブスクエリ 副問い合わせ

SQLではSELECT文による問い合わせを入れ子にすることができます。
入れ子にした問い合わせを副問い合わせと言います。

インジェクション攻撃

ソフトウェアへの攻撃手法の1つです。
文字列入力を受け付けるプログラムに対して、セキュリティを無効化するような不正な文字列を入れてシステムを乗っ取ったり、データを詐取したりします。

不正な文字列と勘違いされないように、MySqlなどではクエリに:=や:をつけます。

WPFと戦った記録 ⑵【MVVM】

前回からの続きです。

WPFと戦った記録 ⑴【MVVM】 - プログラミングと日々思ったことなど

↑こちらが前回の記事になります。

今回はViewModelから復習していきます。

まずはコードから(前回に引き続き、コードは省略している部分があります)

KyukaViewModel.cs

ViewModelにて、BindやCommandの処理をコーディングしていきます。

DTO
データベースからデータを取ってきた際に、データを入れる箱がDTOです。
DTOがあれば直接データベースに接続しなくて良くなります。
(今回のDTOにはkyuka_divisionという名前の箱があります)

using System;
using ...略;

namespace WpfViewBaseprj.ViewModels
{
	public class KyukaViewModel : Commons,ViewModelBase
	{
		//件数表示変数
		private string stCount = string.Empty;

		//登録・更新結果を保存する変数
		private bool isSuccess = false;

		//Viewsフィールド
		BindingListCollectionView views;
		public BindingListCollectionView Views
		{
			get{return views;}
			set
			{
				views = value;
				this.RaisePropertyChanged("Views");
			}
		}

		//データ取得用
		private DataSet cmnDs;
		public DataSet CmnDs
		{
			get{return cmnDs;}
			set{cmnDs = value;}
		}

		//Dtoフィールド
		private WpfViewBaseprjDTOetc.Dto.DtoKyuka dto;
		public WpfViewBaseprjDTOetc.Dto.DtoKyuka Dto
		{
			get{return dto;}
			set
			{
				dto = value;
				this.RaisePropertyChanged("Views");
			}
		}

		//Model設定
		private KyukaModel kyukaModel;
		public KyukaModel KyukaModel
		{
			get{ return Kyukamodel; }
			set
			{
				kyukaModel = value;
				this.RaisePropertyChanged("Kyukamodel");

			}
		}

		//コンストラクタ
		public BindingListCollectionView ListViews{get; set;}
		public DataRow dr;

		//休暇届新規登録用コンストラクタ
		public KyukaViewModel(DataSet commonDs,System.Widows.Forms.ComboBox cmb)
		{
			this.Dto = dto;
			dto = new DtoKyuka();
			this.cmb = commonDs;
			this.Kyukamodel = new kyukaModel();

			dto.kyuka_division.Addkyuka_divisionRow(dto.kyuka_division.Newkyuka_divisionRow());
			DtoKyuka.kyuka_divisionRow conRow = (DtoKyuka.kyuka_divisionRow)dto.kyuka_division.Rows[0];

			//コンボボックス設定
			conRow.sinsei_year = DateTime.Now.Year.Tostring();
			conRow.sinsei_month = string.Format("{0:D2}",DateTime.Now.Month);
			conRow.sinsei_day = ...略;

			this.Views = new BindingListCollectionView(Dto.kyuka_division.DefaultView);

			//バインド用データ設定
			this.InitBindingData();

			//画面クローズ・項目チェックコマンド
			this.CloseCommand = new RelayCommand<Window>(this.CloseWindow);
		}

		//休暇届更新画面用コンストラクタ
		public KyukaViewModel(DataSet commonDs,System.Windows.Forms.ComboBox cmb,DataRow dataRow)
		{
			this.Dto = dto;
			this.cmnDs = commonDs;
			this.kyukaModel = new kyukaModel();
			this.Dto = kyukaModel.test(dataRow);

			this.Views = new BindingListCollectionView(Dto.kyuka_division.DefaultView);
			this.InitBindingData();

			this.CloseCommand = new RelayCommand<Window>(this.CloseWindow);
		}

		//バインド用データ設定
		public void BindingData(string hazimari)
		{
			switch(hazimari)
			{
				case"shinsei":
				    Days = keisansuru(SelectNen,SelectMonth);
				    break;
				case"from":
				    Days2 = keisansuru(SelectNen2,SelectMonth2);
				    break;
			}
		}

		//コンボボックスメソッド(年月日を作る)
		public void Tosituki()
		{
			
			DataTable tosi = new DataTable();

			tosi.Columns.Add("tosinum");
			tosi.Columns.Add("tosi");

			//データテーブルに入れるRowをセット
			for(int year = 2017;year <=2020 ; year++)
			{
				DataRow dr = tosi.NewRow();
				tosi.Rows.Add(dr);

				dr["tosinum"]=year;
				dr["tosi"]=year;
			}
			Nen = tosi;

			//月設定は省略

			//初期値設定
			SelectNen = DateTime.Now.Year;
			SelectMonth = DateTime.Now.Month;
			SelectDay = DateTime.Now.Day;
			SelectNen2 = DateTime.Now.Year;
			SelectMonth2 = DateTime.Now.Month;
			SelectDay2 = DateTime.Now.Day;

		}

		//ラベル設定
		public string TopTitle
		{
			get{return "休暇届";}
		}

		//コンボボックスプロパティ
		private DataTable nen;
		public DataTable Nen
		{
			get{return nen;}
			set
			{
				nen = value;
				this.RaisePropertyChanged("Nen");
			}
		}
		private int selectNen;
		public int SelectNen;
		{
			...略
		}

		//バインド用日付計算設定
		public DataTable keisansuru(int year,int month)
		{
			var dt = new DataTable();
			int days= DateTime.DaysInMonth(year,month);

			dt.Columns.Add("id");
			dt.Columns.Add("days");

			for(int idx=1; idx<=days ; idx++)
			{
			   DataRow dr = dt.NewRow();

			   dt["id"] = string.Format("{0:D2}",idx);
			   dt["days"] = string.Format("{0:D2}",idx);

			   dt.Rows.Add(dr)
			}
			return dt;

		}

		//コマンド
		public RelayCommand<window>
		CloseCommand
		{
			get;
			private set;
		}
		private void CloseWindow(Window window)
		{
			if(window is Entry)
			{
				bool ab = false;

				foreach(System.Windows.Controls.RadioButton rb in ((Entry)window).panel.Children)
				{
					if((bool)rb.IsChecked)
					{
					ab = true;
					break;
					}
				}
				if(!ab)
				{
					System.Windows.MessageBox.Show("入力項目を確認してください",MessageBoxButton.OK);
					return;
				}
			
			   ((KyukaViewModel)((Entry)window).DataContext).btnSave_Click();
			}
			if((window !=null)&&(isSuccess))
			{
				window.Close();
			}

		}

		//継承メソッド(ViewModelBaseから継承されたメソッド)
		public override void btnSave_Click()
		{
			
				KyukaModel kyukaModel = 
					new KyukaModel(this.Dto);
				kyukaModel.InsertData();
			
		}

	}
}

コンボボックスを分岐させているのは、年月日を記入する項目が3つあるからです。
年月日は1つのコンボボックスではなく、3つのコンボボックス(年と月と日)に分かれています。

また画面上で記入した項目は、ModelからデータベースへInsert・・・ではなく、ModelからFa、インターフェース、最終的にDaoからデータベースへ接続しました。
そして接続して取得したデータを、DTOに入れます。

KyukaModel.cs
using ...略;

//休暇届更新画面用
public WpfViewBaseprjDTOetc.Dto.DtoKyuka test(DataRow dr)
{
	WpfViewBaseprjDTOetc.Dto.DtoKyuka testdesu = null;
	Service =
		new WpfViewBaseControlLogic.Service.FaKyuka();

	testdesu = Service.Gettest(this.dto,dr);
	return testdesu;
}

Modelは、ViewModelで処理しないもの(データベースなど)の処理、管理です。
ViewModelは画面のバインド部分を変更させる処理を主にさせ、Modelはデータベースなどの処理、管理をさせます。


以上です。


・・・うーん。これで良いのか不安です。
まだまだ勉強不足です。がんばります。

WPFと戦った記録 ⑴【MVVM】

会社とWebページで学んだことの復習です。

間違っているかもしれませんので、話半分で読んでください。


WPF とは?

正式名称は、Windows Presentation Foundation。

ウィンドウアプリを開発するライブラリ(色んな機能をまとめたもの)です。

WPFの特徴は、下記の項目が主になります。


①見た目を柔軟に変えることができます。

②グラフィックス・ハードウェア(画像の色々な処理をするもの)を活用していて、ベクター・ベース(ベクタは、画像を扱う形式。ラスタ形式もある)のレンダリング・エンジン(データを画面に表示する場所を教えるプログラム)を使っています。
 ベクター・ベースだと、UI要素(UIは、ユーザーとコンピュータとが情報をやり取りをする際に接する、機器やソフトウェアの操作画面や操作方法)の拡大・縮小・回転がスムーズになります。また、ハードウェア・アクセラレーション(高速に処理できる)により、CPUへの負担が少ないそうです。

③外見(画面のデザイン)を設計するXAMLコードと、プログラム処理の内容を設計するコードが分かれています。プログラム処理の内容を設計するコードは、C#VBなどを使います。
 このプログラム処理の内容を設計するコードのことを、「分離コード」とも言います(今後記事の中でも、「分離コード」と書いていきます)。



MVVM ?

MVVMはModel-View-ViewModelの略で、ModelとView、そしてViewModelで役割分担をさせてプログラムを設計する方法です。

このMVVMについて、これから図とコードで詳しく書きます。
コードは実際に書いたものより簡略化しています。(とても長くなってしまうので・・・)



◎動作環境

Visual Studio 2010

.NET Framework 4.0



●Entry画面の図

f:id:boa0203:20170504180055j:plain

赤色の線、紫色の線、黄色の線、緑色の線がGridです。
LabelやComboBoxの隣に書いてある数は、同じ種類のコントロール(Bindは別)がその枠にあることを示しています。
1番下のButtonにだけある※印は、Commandを示しています。

!Bind
Bindを行うと、分離コード側でバインドの宣言をした内容(データ)を変更することができます。

!Command
複数の操作(イベントなど)をまとめて実行できるようにすることができます。

Entry画面・XAMLコード(Entry.xaml
<Window x:Class="WpfViewBaseprj.Entry" 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Name="Main"  >

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*">
<RowDefinition Height="2*">
<RowDefinition Height="以下略………">
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="以下略………" />
</Grid.ColumnDefinitions>

<Label Content="{Binding Path=TopTitle}" Grid.Column="0" Grid.Row="0" />
<ComboBox Grid.Column="1" Grid.Row="略………" 
Name="Cmbox0"  ItemSource="{Binding Path=Nen}" DisplayMemberPath="tosi"
SelectedValuePath="tosinum" SelectedValue="{Binding Path=Views/sinsei_year}"
SelectionChanged="Cmbox0_SelectionChanged"/>
<Button Content="登録" Command="{Binding Path=CloseCommand}" 
 CommandParameter="{Binding ElementName=Main}" />
<略……… />

</Grid>
</Window>
Entry画面・分離コード(Entry.xaml.cs)
using System;


namespace WpfViewBaseprj
{
   public partial class Entry : Window
     {
          public Entry()
          {
          	InitializeComponent();
          }

          //引数によって、ViewModelを分岐させる。
          //休暇届新規登録用コンストラクタ
          public Entry(int kyuka)
          {
          	InitializeComponent();

          	this.DataContext = new kyukaViewModel(commonDs,cmb)
          	this.Title="休暇届";
          	this.Height=800; this.Width=700;
          }

  		 //休暇届更新画面用コンストラクタ			
          public Entry(int p,DataRow dataRow)
          {
          	InitializeComponent();

          	this.chk1.IsChecked = false;
          	this.chk2.IsChecked = false;
          	this.chk3.....略;

          	this.DataContext = new kyukaViewModel(commonDs,cmb,dataRow);
          	this.Title="休暇届更新";
          	this.Height=800; this.Width=700;

          }

          //作業状況報告用コンストラクタ
           public Entry(int p,DataRow dataRow)
          {
          	InitializeComponent();

          	this.DataContext = new SagyoViewModel(string sagyo);
          	this.Title="作業状況";
          	this.Height=600; this.Width=500;

          }

          //宣言

          private DataSet commonDs;
          private System.Windows.Forms.ComboBox cmb;
          private WpfViewBaseDtoetc.Dto.DtoKyuka kyuka_save;

          //コンボボボックスプロパティチェンジ
          private void Cmbox0_SelectionChanged(object sender,SelectionChangedEventArgs e)
          {
          	string hajimari = string.Empty;
          	ComboBox cb = sender as ComboBox;

          	switch(cb.Name)
          	{
          		case"Cmbox0"
          		hajimari ="shinsei";
          		break;

          		case"Cmbox1;"
          		hajimari="from";
          		break;
          	}
          	((kyukaViewModel)this.DataContext).BindingData(hajimari);
          }
     }
 }

分離コードを見ていただくとわかるように、コンストラクタが3つあります。
この3つにあるDataContextは、どれも違う引数です。
引数が違うことによって、ViewModel内でも違うコンストラクタを呼び出すことができます。
そのため、ViewModelにて各々違うバインド設定ができる・・・画面(ここで言うEntry画面)は1つですが、いくつかViewModelがあれば、違うデータを表示する画面を作ることができるのです。


そして実は、今まで画面、Entry画面と書いていたのですが、これをMVVMではViewと呼びます。
Viewで外側(デザイン)を作り、ViewModelから中身(データ)の処理を行います。
・・・なのですが、まだ続きがあります。(MVVMはModel-View-ViewModel。Modelの説明がまだです)
このViewModelから、Modelへ繋がっていくのです。
この復習は、長くなってしまったので次の記事に書きます。



ここまでの復習ですが、ざっくりと書きました。(違っていたらごめんなさい)
参考にしたWebページは以下になります。

WPFについて、とても詳しく書かれてあります。
連載:WPF入門 - @IT

DataContextを、わかりやすく解説されています。
【WPF基礎】脱WPF初心者のための基礎知識 その1〜DataContextってなんぞ?〜: おっさんどりーむ 〜日本語で理解するプログラミング技術〜