본문 바로가기

Refactoring

.net Winform 에서 코드 룩업하기 리펙토링 step3

Step3

 Step2 문제점

 스텝2에서 코드를 바인딩해주는 기본적인 기능을 클래스로 축출하여 개별 Form화면에서 생성만 해주면 되는 방법으로 재사용성을 높였다. 하지만 아직 해결되지 않은 것이 하나 있는데, 단일 코드를 바인딩해주는 기능은 완성하였지만 만약 '구분1', '구분2'와 같이 두개의 코드를 바인딩해야되는데 '구분2'를 바인딩하는 컨트롤의 데이터가 '구분1'의 값에 따라서 달라지는 경우는 아직도 해결이 되지 않고 있다.

Step2 해결

 동적으로 객체가 생성되는 시점에는 '구분1'의 인스턴스가 무엇인지를 알길이 없기 때문에 ComboBoxCodeBinder가 컨트롤의 값도 리턴되는 구조로 만들고 다시 참조할 수 있도록 클래스를 더 변경을 하여 앞의 컨트롤의 데이터를 참조할 수 있는 구조로 변경해보도록 하겠다.

 변경된 클래스 코드 및 화면소스

    public class ComboBoxCodeBinder
    {
        private ComboBox comboBox;
        private ComboBoxCodeBinder refComboBoxCodeBinder;
        private IEnumerable<CodeData> codeDatas;
        public ComboBoxCodeBinder(ComboBox comboBox, IEnumerable<CodeData> codeDatas, ComboBoxCodeBinder refComboBoxCodeBinder)
        {
            this.comboBox  = comboBox;
            this.codeDatas = codeDatas;
            this.refComboBoxCodeBinder = refComboBoxCodeBinder;

            this.comboBox.Enter += new EventHandler(Event_Enter);
        }
        public ComboBoxCodeBinder(ComboBox comboBox, IEnumerable<CodeData> codeDatas)
        {
            this.comboBox  = comboBox;
            this.codeDatas = codeDatas;

            this.comboBox.Enter += new EventHandler(Event_Enter);
        }
        private void Event_Enter(object sender, EventArgs e)
        {
            ComboBox comboBox = sender as ComboBox;

            var bindingData = this.codeDatas.Select( x => x );
            if (this.refComboBoxCodeBinder != null)
                bindingData = this.codeDatas.Where( x => x.RefCodeDiv.Equals( this.refComboBoxCodeBinder.GetCode() ) ).Select( x => x );

            comboBox.DataSource = null;

            if (bindingData.Count() > 0)
            {
                comboBox.DataSource = new BindingSource()
                {
                    DataSource = bindingData
                };
            }

            comboBox.ValueMember   = "Code";
            comboBox.DisplayMember = "Caption";
        }
        public string GetCode()
        {
            object selectedObject = this.comboBox.SelectedItem;

            if (selectedObject == null)
                return string.Empty;

            return ((CodeData)selectedObject).Code;
        }
    }

 

 public partial class Form1 : Form
    {
        private List<CodeData> codeDatas = new List<CodeData>();
        private ComboBoxCodeBinder comboBoxCodeBinder1;
        private ComboBoxCodeBinder comboBoxCodeBinder2;
        public Form1()
        {
            InitializeComponent();

        }
        private void Form1_Load(object sender, EventArgs e)
        {
            codeDatas.Add(new CodeData() { CodeDiv = "01", Code = "01.01", Caption = "매입" });
            codeDatas.Add(new CodeData() { CodeDiv = "01", Code = "01.02", Caption = "매출" });
            codeDatas.Add(new CodeData() { CodeDiv = "01", Code = "01.03", Caption = "기타" });

            codeDatas.Add(new CodeData() { CodeDiv = "02", Code = "02.01", RefCodeDiv = "01.01", Caption = "계약매입" });
            codeDatas.Add(new CodeData() { CodeDiv = "02", Code = "02.02", RefCodeDiv = "01.01", Caption = "현장매입" });
            codeDatas.Add(new CodeData() { CodeDiv = "02", Code = "02.03", RefCodeDiv = "01.02", Caption = "본사매출" });
            codeDatas.Add(new CodeData() { CodeDiv = "02", Code = "02.04", RefCodeDiv = "01.02", Caption = "현장매출" });
            codeDatas.Add(new CodeData() { CodeDiv = "02", Code = "02.05", RefCodeDiv = "01.03", Caption = "기타매입" });
            codeDatas.Add(new CodeData() { CodeDiv = "02", Code = "02.06", RefCodeDiv = "01.03", Caption = "기타매출" });

            this.comboBoxCodeBinder1 = new ComboBoxCodeBinder(comboBox1, codeDatas.Where(x => x.CodeDiv.Equals("01")).Select(x => x));
            this.comboBoxCodeBinder2 = new ComboBoxCodeBinder(comboBox2, codeDatas.Where(x => x.CodeDiv.Equals("02")).Select(x => x), this.comboBoxCodeBinder1);

            button1.Click += new EventHandler(Event_ClickButton);
        }
        private void Event_ClickButton(object sender, EventArgs e)
        {
            string combo1Value = this.comboBoxCodeBinder1.GetCode();
            string combo2Value = this.comboBoxCodeBinder2.GetCode();

            //something...
        }
    }

 코드가 상당히 간결해졌다. 생성시 어떤 코드데이터를 참조하는지 넘겨주고, 앞의 컨트롤의 데이터에 따라 뒤의 컨트롤의 값이 알맞게 바인딩 되어야된다면 앞 컨트롤의 바인딩을 담당하는 객체를 넘겨주면 알아서 작동하도록 변경되었다.