C# - C# 학습 정리 + Windows Form (4)

업데이트:

C# 프로그래밍

파일입출력

파일을 한번에 접근

다음과 같이 코드를 사용하면 문자열을 한번에 파일에 쓸 수 있습니다.

여기서 @를 문자열 앞에 사용하면 \ 같은 특수한 이스케이프 문자를 사용할 수 없도록 해줍니다.

class Program
{
    static void main(string[] args)
    {
        File.WriteAllText(@"C:\test\test.text", "쓸 문자열");
    }
}

파일을 읽을 때는 다음과 같이 접근합니다.

class Program
{
    static void main(string[] args)
    {
        Console.WriteLine(File.ReadAllText(@"C:\test\test.text"));
    }
}


한 줄씩 접근

한 줄씩 접근할 때에는 StreamWriterStreamReader 클래스를 사용합니다.

이들 클래스는 TextWriter 클래스의 상속을 받고있으며 그 위에는 IDisposable 인터페이스가 존재합니다.

따라서 using으로 묶어서 사용하고 예외가 발생하거나 종료시 Dispose 메서드가 호출되도록 합니다.

class Program: IDisposable
{
    static void Main(string[] args)
    {
        using (StreamWriter writer = new StreamWriter(@"C:\test\test.txt"))
        {
            writer.WriteLine("안녕하세요");
        }

        using (StreamReader reader = new StreamReader(@"c:\test\test.txt"))
        {
            string line;
            while((line = reader.ReadLine()) != null)
            {
                Console.WriteLine(line);
            }
        }
                
    }

    public void Dispose()
    {
        throw new NotImplementedException();
    }
}


예외처리

기본적인 예외처리 방법은 Java와 같습니다.

finally

finally 구문은 try ~ catch문에서 반드시 실행하도록 하기위한 구문입니다.

만약 예외가 발생하여 catch 블록을 통해 return, break, continue를 하더라도 finally는 실행하고 해당 메서드를 종료합니다.

단 finally 내부에서는 return이 불가능합니다. 구문 내부를 실행하고 끝내게 되는데 return이 호출되면 구문을 벗어나기 때문입니다.


예외 구분을 통한 중첩 catch

여러가지 예외 객체를 인자로 catch문을 중첩해서 사용할 수 있습니다.

try
{

}
catch (FormatExcepcion exception)
{

}
catch (IndexOutOfRangeException exception)
{

}


당연하게도 다음과 같이 var 키워드를 사용하여 catch 구문의 인자로 사용할 수는 없습니다.

catch (var exception)
{

}


강제 예외 발생

강제로 예외를 발생 시킬 수도 있습니다. throw 키워드를 사용합니다.

try
{
    throw new Exception();
}
catch (Exception exception)
{

}


강제로 예외를 발생시키는 경우는 다음과 같이 조건에 맞지 않을 경우 많이 사용합니다.

// 바로 종료
if() { }
else { throw new Exception("에러 발생"); }

// 예외 처리만
try
{
    if() { }
    else { throw new Exception("에러 발생"); }
}
catch (Exception exception)
{

}


사용자 정의 예외

사용자가 직접 예외 클래스를 만들어서 사용할 수 있습니다.

class CustomException: Exception
{
    public CustomException(string message) : base(message) // 부모 클래스에 메시지를 전달하여 생성자를 호출
    {

    }
}

...
...

try
{
    throw new CustomException("예외발생");
}
catch (CustomException exception)
{
    
}

윈도우 폼

레이블과 링크 레이블

 public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            Label label = new Label()
            {
                Text = "글자",
                Location = new Point(10, 10)
            };

            LinkLabel linklabel = new LinkLabel()
            {
                Text = "글자",
                Location = new Point(10, 50)
            };

            linklabel.Click += LabelClick;

            Controls.Add(label);
            Controls.Add(linklabel);
        }

        private void LabelClick(object sender, EventArgs s)
        {
            throw new NotImplementedException();
        }
    }


체크박스, 라디오 버튼, 그룹 박스

체크박스, 라디오 버튼도 위의 레이블처럼 적용하면 됩니다.

라디오버튼의 경우 라디오 버튼이 부모 요소의 지배를 받기 때문에 자동으로 1개만 선택가능하도록 제어합니다.

이를 거부하고 그룹으로 나누어서 라디오 버튼을 선택할 수 있게 하려면 그룹박스를 이용합니다.

다음은 간단한 예제 입니다.

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            GroupBox groupbox1 = new GroupBox();
            GroupBox groupbox2 = new GroupBox();
            RadioButton radio1 = new RadioButton();
            RadioButton radio2 = new RadioButton();
            RadioButton radio3 = new RadioButton();
            RadioButton radio4 = new RadioButton();
            Button button = new Button();

            groupbox1.Text = "식물";
            groupbox2.Text = "물고기";
            radio1.Text = "감자";
            radio2.Text = "고구마";
            radio3.Text = "광어";
            radio4.Text = "우럭";
            button.Text = "클릭";

            groupbox1.Size = new Size(120, 100);
            groupbox2.Size = new Size(120, 100);

            groupbox1.Location = new Point(10, 10);
            groupbox2.Location = new Point(140, 10);

            radio1.Location = new Point(10, 30);
            radio2.Location = new Point(10, 60);
            radio3.Location = new Point(10, 30);
            radio4.Location = new Point(10, 60);
            button.Location = new Point(10, 120);

            button.Click += ButtonClick;

            groupbox1.Controls.Add(radio1);
            groupbox1.Controls.Add(radio2);

            groupbox2.Controls.Add(radio3);
            groupbox2.Controls.Add(radio4);

            Controls.Add(groupbox1);
            Controls.Add(groupbox2);
            Controls.Add(button);

        }

       

        private void ButtonClick(object sender, EventArgs s)
        {
            foreach (var outerItem in Controls)
            {
                if(outerItem is GroupBox)
                {
                    foreach(var innerItem in ((GroupBox)outerItem).Controls)
                    {
                        RadioButton radiobutton = innerItem as RadioButton;
                        if(radiobutton != null && radiobutton.Checked)
                        {
                            MessageBox.Show(radiobutton.Text);
                        }
                    }
                }
            }
        }
    }


데이터 바인딩

콤보 박스와 리스트 박스를 예로 생성한 후, 모델 클래스를 작성하고 이들을 데이터 바인딩한다.

그 후, 데이터 바인딩 소스에 데이터를 추가한다.

원래라면 데이터베이스와 연동하는 경우가 많지만 간단한 예로 다음과 같이 작성한다.

image

image

image


class Product
    {
        public string Name { get; set; }
        public int Price { get; set; }
    }
 public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            productBindingSource.Add(new Product() { Name = "감자", Price = 500 });
            productBindingSource.Add(new Product() { Name = "사과", Price = 600 });
            productBindingSource.Add(new Product() { Name = "토마토", Price = 800 });
        }

    }

image


이제 클릭에 따른 이벤트를 등록합니다.

보통 SelectedItem 이나 SelectedValue 속성을 이용합니다.

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            productBindingSource.Add(new Product() { Name = "감자", Price = 500 });
            productBindingSource.Add(new Product() { Name = "사과", Price = 600 });
            productBindingSource.Add(new Product() { Name = "토마토", Price = 800 });

            comboBox1.SelectedIndexChanged += DataSelect;
        }

        private void DataSelect(object sender, EventArgs e)
        {
            if (sender is ComboBox)
            {
                ComboBox comboBox = (ComboBox)sender;
                MessageBox.Show(comboBox.SelectedValue.ToString());
            }
            else if (sender is ListBox)
            {
                ListBox listBox = (ListBox)sender;
                MessageBox.Show(listBox.SelectedValue.ToString());
            }
        }
    }


데이터 그리드 뷰를 만들어서 출력할 수도 있습니다.

데이터 바인딩을 이미 했기 때문에 데이터 소스만 선택하여 출력하면 다음과 같습니다.

image

데이터 바인딩이 된 상태에서 바인딩 소스에 데이터를 CRUD 처리를 하게 되면 화면에 바로 반영됩니다.


  • 참고자료: C# 프로그래밍 - 한빛아카데미

댓글남기기