* 입력/출력/수정/삭제/검색/저장/종료/백업 기능을 WinForm에서 만듦.
==> Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace 주소록
{
static class Program
{
/// <summary>
/// 해당 응용 프로그램의 주 진입점입니다.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
}
==============================================================================================
==> Address.cs
using System;
namespace 주소록
{
class Address
{
public int Num { get; set; }
public string Name { get; set; }
public string Mobile { get; set; }
public string Email { get; set; }
}
}
==============================================================================================
==> MainForm.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace 주소록
{
public partial class MainForm : Form
{
private List<Address> addr;
private string dir = System.IO.Path.Combine( // Path.Combine : 경로 묶어준다.
Application.StartupPath, "MyAddress.txt"); // Application.StartupPath : exe파일과 같은 경로로 지정해준다.
public MainForm()
{
InitializeComponent();
addr = new List<Address>();
}
private void MainForm_Load(object sender, EventArgs e)
{
if (File.Exists(dir))
{
LoadData();
}
this.sslCount.Text = "등록수 : " + addr.Count.ToString();
if (addr.Count > 0)
{
ShowRecord(0); // 첫번째 데이터를 표시
btnAdd.Text = "추가";
}
}
private void LoadData()
{
StreamReader sr = new StreamReader(dir, Encoding.Default); // StreamReader의 생성자를 통해 파일을 연다.(-> open)
while (sr.Peek() >= 0) // -1 : 더 이상 읽을 문자가 없을 때
{
string[] arr = sr.ReadLine().Trim().Split(',');
if (arr[0] != "" && arr[0] != null)
{
Address a = new Address();
a.Num = Convert.ToInt32(arr[0]); // 번호 : 인덱스 + 1
a.Name = arr[1];
a.Mobile = arr[2];
a.Email = arr[3];
addr.Add(a);
}
}
sr.Close(); // StreamReader를 통해 파일을 열었으면 꼭 닫아줘야 한다!
sr.Dispose(); // 해제
DisplayData();
}
private void btnAdd_Click(object sender, EventArgs e)
{
if (btnAdd.Text == "입력")
{
Address a = new Address();
a.Num = addr.Count + 1; //
a.Name = txtName.Text.Trim();
a.Mobile = txtMobile.Text.Trim();
a.Email = txtEmail.Text.Trim();
addr.Add(a);
DisplayData(); // 출력
}
else
{
btnAdd.Text = "입력";
}
ClearTextBox();
}
// Clear관련
private void ClearTextBox()
{
txtName.Text = txtMobile.Text = txtEmail.Text = String.Empty;
}
// 출력관련
private void DisplayData()
{
var q = (from a in addr select a).ToList();
this.dgvAddress.DataSource = q;
}
// 검색전용
private void DisplayData(string query)
{
var q = (from a in addr
where
a.Name == query ||
a.Mobile == query ||
a.Email == query
select a).ToList();
this.dgvAddress.DataSource = q;
}
// 저장관련 -> 텍스트파일에 저장함.
private void btnSave_Click(object sender, EventArgs e)
{
if (addr.Count > 0)
{
SaveData();
}
}
private void SaveData()
{
//if (!File.Exists(dir)) // 파일이 없으면 생성
//{
// File.Create(dir); // 해당경로에 파일이 없으면 생성
//}
// 레코드는 엔터구분, 필드는 콤마구분으로 저장
StringBuilder sb = new StringBuilder();
int index = 0;
foreach (Address a in addr)
{
sb.AppendLine(String.Format("{0},{1},{2},{3}"
, ++index, a.Name, a.Mobile, a.Email)); // 번호 : 인덱스 + 1
}
StreamWriter sw = new StreamWriter(dir, false, Encoding.Default); // "StreamWriter"는 파일이 없으면 만들어서 저장한다.
sw.Write(sb.ToString());
sw.Close(); // 닫기
sw.Dispose(); // 해제
MessageBox.Show("저장되었습니다.");
}
// 백업 관련
private void miBackup_Click(object sender, EventArgs e)
{
string name = Path.GetFileNameWithoutExtension(dir);
string ext = Path.GetExtension(dir).Replace(".", "");
// MyAddress20100101.txt로 저장가능하도록
string newDir =
Path.Combine(Application.StartupPath,
String.Format("{0}{1}.{2}"
, name
, String.Format("{0}{1:0#}{2}"
, DateTime.Now.Year
, DateTime.Now.Month
, DateTime.Now.Day.ToString().PadLeft(2, '0')
)
, ext
)
);
if (File.Exists(dir))
{
File.Copy(dir, newDir, true); // 원본을 복사해서 백업해놓는다.
}
}
private void miExit_Click(object sender, EventArgs e)
{
Application.Exit();
}
private int currentIndex = -1;
private void dgvAddress_CellClick(object sender, DataGridViewCellEventArgs e)
{
//currentIndex = e.RowIndex; // 현재 인덱스를 필드에 보관
DataGridViewCell dgvc = dgvAddress.Rows[e.RowIndex].Cells[0];
currentIndex = Convert.ToInt32(dgvc.Value.ToString()) - 1;
if (currentIndex != -1)
{
ShowRecord(currentIndex);
}
}
private void ShowRecord(int index)
{
// 현재 선택된 인덱스 + 1을 번호 출력
this.txtNum.Text = (index + 1).ToString();
this.txtName.Text = addr[index].Name;
this.txtMobile.Text = addr[index].Mobile;
this.txtEmail.Text = addr[index].Email;
btnAdd.Text = "추가";
txtGo.Text = txtNum.Text; // 현재 선택된 인덱스 값 출력
}
private void btnModify_Click(object sender, EventArgs e)
{
if (currentIndex != -1 && blnModified == true) // currentIndex != -1 : 선택된 데이터가 있다면
{
// 변경된 데이터로 addr 개체의 현재 인덱스 데이터 변경
addr[currentIndex].Name = txtName.Text;
addr[currentIndex].Mobile = txtMobile.Text;
addr[currentIndex].Email = txtEmail.Text;
MessageBox.Show("수정되었습니다.", "수정완료");
DisplayData();
blnModified = false; // 다시 초기화
}
}
// 3개 텍스트박스에서 KeyPress 이벤트 발생시 호출
private bool blnModified = false;
private void txtModify_KeyPress(object sender, KeyPressEventArgs e)
{
if (txtNum.Text != "") // 데이터가 로드된 상태에서만
{
blnModified = true; // 변경되었다...
}
}
private void btnDelete_Click(object sender, EventArgs e)
{
if (txtNum.Text != "" && currentIndex != -1) // txtNum.Text != "" : 널값이 아니라면... / currentIndex != -1 : 선택된 상태가 아니라면...
{
DialogResult dr =
MessageBox.Show("정말로 삭제하시겠습니까?", "삭제확인"
, MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (dr != DialogResult.No)
{
// 메모리 상에서 현재 레코드 삭제
addr.RemoveAt(currentIndex);
DisplayData();
}
}
}
// 처음, 이전, 다음, 마지막 버튼에 대한 공통 이벤트
private void btnMove_Click(object sender, EventArgs e)
{
Button btn = sender as Button;
if (btn == btnFirst)
{
if (currentIndex > 0)
{
currentIndex = 0; // 0번째 인덱스로 표시
}
}
else if (btn == btnPrev)
{
if (currentIndex > 0)
{
currentIndex--;
}
}
else if (btn == btnNext)
{
if (currentIndex < addr.Count - 1)
{
currentIndex++;
}
}
else if (btn == btnLast)
{
if (currentIndex != -1) // 데이터가 있다면
{
currentIndex = addr.Count - 1;
}
}
ShowRecord(currentIndex); // 다시 데이터 표시
}
private void btnGo_Click(object sender, EventArgs e)
{
if (txtGo.Text != "" && Convert.ToInt32(txtGo.Text) > 0
&& Convert.ToInt32(txtGo.Text) <= addr.Count)
{
ShowRecord(Convert.ToInt32(txtGo.Text) - 1);
}
}
private void btnSearch_Click(object sender, EventArgs e)
{
DisplayData(txtSearch.Text);
}
}
}
< 실행결과 >
--> 4명의 데이터가 존재하는 상황에서 '폼'을 새로 load했을 때 초기화면(데이터가 존재하고 있을 때는 '폼' load시에 초기화면이 "입력"버튼이 "추가"버튼으로 바뀌어져 나온다.) '폼'의 '이름', '휴대폰', '이메일' TextBox에 데이터를 입력한 후 "추가"버튼을 누르면 '폼'아래의 'DataGridView'에 데이터가 출력되고 "저장"버튼을 누르면 "저장되었습니다."라고 'MessageBox'가 나오며, 데이터가 "텍스트파일(메모장)"로 저장된다.
--> '폼'의 '이름', '휴대폰', '이메일' TextBox에 데이터를 입력한 후 '저장'하였을 때 해당폴더(.exe파일이 있는 'Debug'폴더)에 "텍스트파일(메모장)"형태로 데이터가 저장된다.
--> "추가"버튼을 누르면 "추가"버튼의 텍스트가 "입력"으로 바뀌면서 동시에 '이름'/'휴대폰'/'이메일'의 TextBox가 Clear되어진다.('번호'의 TextBox'속성'은 "Readonly"로 설정해서 값을 변경할 수 없다.)