내가 아는거/WPF2018. 3. 8. 15:46

이번 건은 내가 바보짓을 한 경우인데, 혹시라도 나같은 사람이 또 있을까? 싶어서 기록합니다.


WPF 프로그래밍을 하다보면 ObservableCollection을 사용하는 경우가 많고, View와 Viewmodel의 바인딩에 편리하게 사용합니다.

그런데, 클래스에 프로퍼티를 만들때도 Collection이 필요하면 습관적으로 ObservableCollection으로 만들었죠.

아무일도 없었습니다.

그런데 성능문제가 있어서 검토하다가 발견한게...

 ObservableCollection OCollection = new ObservableCollection();
 List ListText = new List();
 private void Button_Click(object sender, RoutedEventArgs e)
 {
     for (int i = 0; i < 1000000; i++)
     {
         OCollection.Add(i.ToString());
     }

     for (int i = 0; i < 1000000; i++)
     {
         ListText.Add(i.ToString());
     }
 }

ObservableCollection과 List에 1000000개의 아이템을 넣어봤더니, 속도가 2배정도 차이가 납니다.

필요없는곳에 ObservableCollection을 남발하지 맙시다 ㅜㅜ

Posted by zinzza
내가 아는거/WPF2012. 12. 4. 11:08

1. ObservableCollection 에서 View 를 생성한다.

2. 생성된 View에 Filter를 적용한다.

3. 조건이 변경되면 View를 Refresh해준다.


일반적인 Collection에서 추가해줘야 하는것은...

View 를 구해서 Filter를 적용하는 소스, Filter구현, 조견변경시 Refresh 해주는 코드 1줄.

이렇게 3가지 입니다.


#region Students   
private ObservableCollection items = new ObservableCollection();
public ObservableCollection Items       
{            
    get 
    {
        if (this.items == null)  
        {
            this.items = new ObservableCollection();                
        }
        var view = CollectionViewSource.GetDefaultView(this.items);    
        if (view.CanFilter)      
        {
            view.Filter = this.TestFilter;    
        }        
        return this.items;   
    }      
} 
       
private bool TestFilter(object item)   
{
    string Item = item as Student;
    if (this.SelectedGender == null ) return true;  
    if (this.SelectedGender== Item.Gender) return true;     
    return false;      
}
#endregion  

#region SelectedGender  
private string selectedGender;   
public string SelectedGender   
{           
    get { return this.selectedGender; }
    set      
    {       
        if (this.selectedGender != value)      
    {                  
            this.selectedGender = value;                    
            this.RaisePropertyChanged("SelectedGender");                    
            CollectionViewSource.GetDefaultView(this.Items).Refresh();   
        }      
    }        
}
#endregion



Posted by zinzza
내가 아는거/WPF2012. 11. 20. 01:09

안녕하세요 zinzza, 연두父, 이경배입니다.

4회입니다. 이번엔 지난번과 동일하게 뷰모델에서 Collection을 선언하고 뷰의 DataGrid와 연결해서 사용하는 방법을 알아보겠습니다.

Collection을 만들면서 모델도 하나 만들어보고요.(거창해보이지만 그냥 클래스입니다)


일단... 프로그래머 분들께서는 이 글의 오류를 찾아 저에게 제출해주시고, 그럴 목적이 아니시라면 읽지 말고 나가주세요.(부끄로아요ㅜㅜ)


  1. Model(Class)을 하나 선언하겠습니다.

  2. 뷰모델에 생성한 Model의 Collection 을 선언합니다.

  3. 뷰에 DataGrid를 하나 올려서 Collection과 연결합니다.

  4. 뷰에 TextBlock 컨트롤을 올려서 선택된 Collection 중 선택된 Data가 어느것인지 표시합니다.

  5. DataGrid에서 수정한 데이타가 Collection에 반영되는것을 확인합니다.


바로 시작합시다!!!!!!!

당연히! 2-2회를 보시고(이젠 안보셔도 되려나?) 기본틀을 준비해 주시기 바랍니다^^;


1. Human Model(Class)을 하나 선언하겠습니다.


드디어? 처음으로 Model을 만드는군요. 근데 사실 Model은 별게 없습니다.

Class죠^^;

가벼운 마음으로


솔루션 탐색기에서 마우스 오른쪽 버튼을 눌러 클래스를 추가해 줍니다.


클래스 이름은 GDFMember.cs 로 하죠.

CgdfMember.cs 처럼 클래스 접두사를 붙이지 않는걸 이상하게? 생각하시는 분들도 있으실껍니다.

저도 처음에 어떻게 해야 하나(제가 다른 언어를 많이 안해봐서요) 고민했는데 저희 회사에서는 특별히 접두사를 붙히지 않습니다.

그저 클래스, 프로퍼티 이름은 대문자로 시작하고, 컬렉션은 s를 붙혀서 복수형으로, bool 타입은 is를 붙히는 정도?(int나 double같은건 아무것도 안붙힙니다.)

그냥 그런가보다 하고 썼는데 C# + VS 는 마우스만 올려도, 커서만 가도 어떤 형태인지 바로 알 수 있기 때문에 접두사를 쓰지 않아도 되는 정도더군요.

단점은 다른 사람들 코드를 볼때 상당히 거슬린다는거-_-?


아무튼 이번 강좌는 제 습관대로 갑니다^^


그 다음 프로퍼티들을 선언합니다. Name, Job, Career 3개만 선언하겠습니다.


) ObservavleObject를 상속받았습니다.


Job과 Career는 접어놨습니다.(공간 아껴보겠다고... 가 아니고 모니터 밑으로 내려가서 캡쳐하기 귀찮아요 -_-;)



2. 뷰모델에 생성한 Model의 Collection 을 선언합니다.


다들 아시리라 보고~~~ MainViewModel에서 GDFMember를 갖고 Collection을 선언하겠습니다.

Collection은 지난번에 설명드렸죠? ㅎㅎㅎ


아~! using System.Collections.ObjectModel; 를 추가해주는걸 잊지 마시고^^;

ObservableCollection에 밑줄가는분들!ㅋㅋㅋ


그리고 Members에 뭔가를 채워줘야겠죠. 놀개영 사이트의 필자분들 프로필을 보고 대충... 


신상정보따위 ㅋ


아! 그 전에 다시 GDFMember에 가서 생성자를 하나 만드는게 편하겠군요!

요딴식으로 ㅋ


그리고 자꾸 왔다갔다 해서 죄송한데^^;

MainViewModel의 생성자로 가서 자료를 추가 해 줍시다.


위 내용은 실제와 다를 수 있습니다.


아~~~~ 다 된거 같네요.

이젠 익숙치 않은 XAML로 갈 차례입니다. ㅜㅜ



3. 뷰에 DataGrid를 하나 올려서 Collection과 연결합니다.


먼저 MainWindow.xaml 을 열고 DataGrid를 하나 올려놓고 사이즈를 적당히 조정합니다..


아... 그리고 DataGrid.Colimns 태그와 DataGridTextColumn 을 넣어줘야 Header가 나오는거~

기억하시죠^^?

이렇게 말이죠^^;


일단 DataGrid 컨트롤을 올렸으니 이제 ViewModel과 연결을 해볼까요?


ㅎㅎㅎ 소스를 보면요.

이렇게~~~~


방법을 설명하자면~

1. 지난번에 해본거처럼 DataGrid 태그 안에 ItemsSource를 Members로 Binding 합니다.

2. 각 Column에 GDFMember의 프로퍼티를 Binding 합니다.


쉽죠~~~?


지난 시간에 설명하기 귀찮아서 이번으로 넘긴 "쩜" 기억하시나요?


기억 안나신다고요? 그럼 이 이미지는요?

아... 이제 기억나시죠^^?



오늘 설명한걸 보면 ItemsSource에 Members를 binding 하고, 각 Column에 GDFMember의 프로퍼티를 하나씩 써줬죠?

하지만 지난번 설명한 예제의 경우 ItemsSource에 Binding 된 Names의 경우 string 의 컬렉션이기 때문에 Column에 Binding해줄 프로퍼티가 없죠.

아니! 정확히 말하면 Column에 Binding 될 프로퍼티? 가 컬렉션 멤버(string) 자체가 되겠죠.

그런 경우 "쩜"을 찍어줍니다^^;


두가지를 같이 설명해야 편할꺼 같아서 뒤로 미뤄뒀던거에요~~~~




4. 뷰에 TextBlock컨트롤을 올려서 선택된 Collection 중 선택된 Data가 어느것인지 표시합니다.


자~~~ 힘드네요.

이제 거의 끝입니다~~


우선 선택된 Data가 뭔지 알아야 하는 거 같으니 MainViewModel에 SelectedMember라는 프로퍼티를 하나 추가해줍니다.



그리고 이건 MainWindow.xaml에서 DataGrid의 SelectedItem에 바인딩해줘야 합니다.



이렇게 하면 선택된 데이타는 자동으로 SelectedMember가 되겠죠.

이제 TextBlock을 추가해서 선택된 데이타가 잘 나오는지만 확인하면 되겠네요^^;


TextBlock은 이왕 하는거 6개를 추가합니다-o-;

많은거 같지만 3개의 프로퍼티를 다 보여주려고 그런겁니다.

근데 왜 3개가 아니고 6개냐구요?

제목 써야죠 제목!


이런식으로 배치해줍니다^^;


그리고 뒤에 3개는 SelectedMember의 프로퍼티를 Bindgin해줘야겠죠?

이런식으로 "." 을 이용할 수도 있습니다. 


자~~~ 이제 F5!!!!!!!!!!!!!!!!!!

실행 해서 선택된 값이 잘 나오는걸 확인합니다! 

...........................................................................................

...

.

.

.

.

.

.

..

.

.

.

.

.

.

.

.

.

..

.

.

.

.


헉!  실행해보니 제가 실수를 했네요.

TextBlock을 올려야 되는데 제가 실수로 TextBox를 올렸습니닼ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 

역시 정신잌ㅋㅋㅋㅋㅋㅋ 자야됰ㅋㅋㅋㅋㅋㅋㅋㅋㅋ

ㅜㅜ


뭐 그레도 실행은 잘 됩니다^^;


자... 저처럼 아이템을 하나 선택하신 뒤 오른쪽에 잘 반영되는지 확인해 보세요^^;


5. DataGrid에서 수정한 데이타가 Collection에 반영되는것을 확인합니다.


이번엔 수정하실게 없습니다.

4에서 다 끝났어요^^


그럼... 이번엔 확인만 해보면 되는거겠죠?


* 셀? 을 하나 선택하신 후 값을 수정해보세요. 그러면 값이 잘 바뀝니다.

이것저것 수정해보세요^^;


이렇게 경력(int 형)에 문자열을 넣으면 자동으로 막아주기도 합니다.^^;



* 저처럼 실수하셨던지, 아니면 저를 따라하셨던지, 혹시 만들어놓고 또 수정하셨던지...

오른쪽에 TextBox를 올리신 분은 오른쪽 선택된 데이타가 표시된 부분에서 수정하시면 DataGrid의 값도 수정되는걸 보실 수 있습니다^^; 

이것이 데이타가 변경된 이벤트를 따로 구현하지 않아도 되는 MVVM의 묘미! 입니다.


자~~ 오늘은 여기까지만 하겠습니다.


다음을 기대!!!!!!!!!






















하지 마세요ㅜㅜ








Posted by zinzza
내가 아는거/WPF2012. 11. 19. 19:44

안녕하세요 zinzza, 연두父, 이경배입니다.

3회입니다. 이번엔 뷰모델에서 Collection을 선언하고 뷰와 연결해서 사용하는 방법을 알아보겠습니다.


일단... 프로그래머 분들께서는 이 글의 오류를 찾아 저에게 제출해주시고, 그럴 목적이 아니시라면 읽지 말고 나가주세요.(부끄로아요ㅜㅜ)


여기서 Collections라고 써있는놈을 한번 사용해본다는거죠 ^^;


이번에 해야 할 일을 먼저 나열해보겠습니다.


  1. 뷰모델에 Collection하나를 선언합니다.

  2. 뷰에 ComboBox를 하나 올려서 Collection과 연결합니다.

  3. 뷰에 ListBox를 하나 올려서 Collection과 연결합니다.

  4. 뷰에 DataGrid를 하나 올려서 Collection과 연결합니다.

  5. 뷰에 TextBlock을 하나 올리고 Collection 중 선택된 Data가 어느것인지 표시해봅니다.


우선 2-2회를 보시고 기본틀을 준비해 주시기 바랍니다^^;

준비 되셨나요?

순서대로 갑시다!
1. 뷰모델에 Collection 하나를 선언합니다.
MainViewModel.cs 를 열어서 선언합시다!

지난 2-2 에 있던 코드조각을 사용하면 편리합니다.  그냥 타이핑하시는것도 좋고요^^;
Collection 이름은 Names라고 했습니다. 저는 주로 뒤에 s를 붙혀서 복수형으로 표시합니다.

어라? 근데 ObservableCollection에 밑줄이 가있죠?
맨 위로 올라가셔서 
using System.Collections.ObjectModel;
을 추가해주시면 사라질껍니다.

그나저나... Names를 활용하려는데 아무것도 없는 빈 Collection이니... Names에 뭔가를 넣어놔야겠죠?

실제 프로그램에서야 이런저런 경로로 Item들을 넣겠지만 지금은 그냥 생성자에서 넣어보겠습니다.
이렇게요^^;

코드는 따로 설명 안드려도 될만큼 쉽습니다.
그럼 Collection 선언이 끝났으니 뷰로 가볼까요?

2. 뷰에 ComboBox를 하나 올려서 Collection과 연결합니다.


MainWindow.Xaml 파일을 열고 도구상자에서 ComboBox를 더블클릭해서 ComboBox를 추가합니다.

그리고 Xaml코드를 보시면 Combobox를 찾으실 수 있을텐데요 그 맨 뒤쪽에 
 ItemsSource="{Binding Names}" 
를 추가해 주세요.
이렇게요.

ComboBox, ListBox, DataGrid 등의 컨트롤에는 ItemsSource라는 속성이 있습니다.
Collection은 바로 ItemsSource에 연결(Binding)하는 Property의 일종이라고 생각하시면 됩니다.
ItemsSource가 없는 컨트롤은요??? 당연히 연결 안됩니다^^;

자~~~ 이제 실행! 
이렇게 잘 연결된걸 보실 수 있습니다.

3. 이번엔 ListBox를 올려볼 순서네요.
이번에도 간단하게 도구상자에서 ListBox를 더블클릭! 후 마우스를 이용해 대~충 위치를 잡아보시고요^^;
이렇게~

Xaml코드에서 ListBox에 마찬가지로 
 ItemsSource="{Binding Names}" 
를 추가해 주세요.

끗~! 

그리고 실행해서 한번 보시죠^^;
아~ 이뿌다~~~ 잘했어요~~~

4. 자~이번엔 자신감 완충해서 DataGrid ~GOGO~!
똑같은걸 3번 하려니 짜증도 나시죠?

도구상자에서 이렇게 DataGrid추가해 주시고~~~

누가 안시켜도 이렇게 DataGrid Tag 찾아서 ItemsSource 딱! 추가해주시고~

GOGO! F5!!!!!


.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.


자... 뭐가 문제인가.

문재인이 문제인가.....................아 이건아닌데-_-


ㅎ 너무 좌절하실건 없고요, DataGrid의 사용법이 잘못된 문제입니다. 

우리가 알고 있는 DataGrid는 맨 위에 회색줄로 Data 이름이 써있잖아요? 뭐 그런것도 입력해줘야 하고... 등등 아무튼!

사용법을 좀 보시죠.


수정한 xaml 입니다.


빨간색 사각형 부분이 전부 바뀐겁니다.

우선 />>로 바뀌었습니다.

그리고 마지막줄에 </DataGrid>가 들어갔죠.

이건 xaml의 기초에 해당하는 부분인데요(html을 조금 보신분들은 이해하실겁니다.) <DataGrid> 가 한줄에 모든걸 다 표현할 수 있으면 /> 로 끝났다는걸 표시하는거고, 지금처럼 추가해야 하는 속성이 많거나 하위속성이 있다면 </DataGrid>로 끝을 표시합니다.

음... 별거 아닌데 설명이 길어지니 이정도로만 하고 넘어가겠습니다.(부끄러워서 글씨가 작아지네요 ㅜㅜ)


아무튼!!!

그리고 <DataGrid.Columns>와 </DataGrid.Columns> 사이에

<DataGridTextColumn Header="이름"   Binding="{Binding .}"/>

가 추가되어있는거죠.

이 DataGrid의 칼럼을 정의하는겁니다.

우리는 이름밖에 없으니 이름 한줄이 들어가있는거고요.


칼럼에는 DataGridTextColumn 외에도 


DataGridHyperlinkColumn - URI 데이터를 표시하는 데 사용합니다.

DataGridComboBoxColumn - 열거형 데이터를 표시하는 데 사용합니다.

DataGridTextColumn - 텍스트를 표시하는 데 사용합니다.

DataGridCheckBoxColumn - 부울 데이터를 표시하는 데 사용합니다.


등의 칼럼을 사용할 수 있습니다.


출처: MSDN


Header는 설명 안드려도 대충 눈치채셨을거라 믿습니다^^;


Binding="{Binding .}" 

을 설명드려야겠네요.

"Binding = 연결" 이라고 몇번 보셨더니 아시겠죠?

자 연결을 하는데... 이전엔 Property이름이나 Collection이름을 적었는데 왠 쩜??!? 


점-_-??


아............ 이건 다음회에 설명드려야 겠네요.

다음에 하려고 계획한걸 먼저 하면 이해가 쉬울꺼 같아서요.


강좌 마지막에 민소희가 나오더니... 드라마같은 찝찝한 마무리가 되겠군요.

왜 너는 나를 만나서~~


아 아무튼 실행을 해보시면 

좀 찝찝하지만 성공~


5. 그러면 마지막! 선택된 데이타를 TextBlock에 표시해보죠,


뷰에 TextBlock추가!(이건 쉽죠? 화면캡쳐도 뺄께요 ㅎ)

그다음 ViewModel에 SelectedName이라는 Property를 하나 추가해줍니다.

선택된 데이타가 뭔지를 저장하려고 만든 Property입니다.


그럼 이 SelectedName을 뷰와 연결해보겠습니다.

TextBlock의 Text 속성을 Text="{Binding SelectedName}" 으로 수정해줍니다.



각 컨트롤(ComboBox, ListBox, DataGrid)에 SelectedItem="{Binding SelectedName}" 을 추가해줍니다.


어어 힘들다~~

자~~ 이제 실행~~~ F5 해보시면 마지막 결과물을 보실 수 있습니다.

특정 이름을 선택하면 TextBlock에 선택된 이름이 나올뿐 아니라 다른 컨트롤의 선택된 아이템도 같이 변경되는 모습을 보실 수 있습니다.




아.............. 연두를 재워놓고 열심히 써봤는데... 지금 1시 25분이네요.
오류고 뭐고 이제 올려놓고 자야겠습니다 ㅜㅜ
놀게영(http://gamedevforever.com)에 글 올려주시는 필자님들 너무 수고가 많으세요.
글 하나 올리기 이렇게 힘든데 ㅜㅜ


아무튼 오늘도 
달땡님... 소고기가 필요해요~




















Posted by zinzza
내가 아는거/WPF2012. 11. 19. 15:45


안녕하세요 zinzza, 연두父, 이경배입니다.

3회가 아니고 2-2 인 이유는 앞으로 뭔가를 할때 기본이 되는 틀?을 만드는 단계까지를 계속 설명하기 귀찮아서 따로 빼놓기 위해서 입니다.

뭐 0회나 기타 다른 숫자를 만들긴 뭣하고... 슬쩍 2-2로 만들어봅니다.


이 글의 대상은 엄청 간단한 C#책을 살짝쿵 읽어본 기획자, 대학, 학원등에서 C#프로그램을 좀 배운 수준의 사람들을 대상으로 적었습니다.



1. 새 프로젝트를 만들어주세요.





2. 제가 첨부해 놓은 Apparelbase.MVVMBase.dll을 참조에 추가합니다.

Apparelbase.MVVMBase.dll


솔루션 탐색기의 참조에서 오른쪽버튼-> 참조추가-> 찾아보기 에서 찾아 추가해주시면 됩니다.





3. ViewModel을 추가 해야 합니다.
클래스 이름은 알아보기 쉽게 MainViewModel.cs 를 기준으로 하겠습니다.
솔루션 탐색기의 프로젝트 이름에서 오른쪽버튼 -> 추가-> 클래스 



MainViewModel.cs를 열어서 위의 빨간부분을 입력합니다.


4. ViewModel과 View를 연결하는 코드를 입력합니다.(연결합니다)
솔루션 탐색기에서 MainWindow.xaml.cs를 선택해 줍니다.



그리고 연결하는 코드를 넣어주죠.


여기까지입니다^^;

이렇게해 둔걸 틀로, 뷰모델(MainViewModel.cs)과 뷰(MainWindow.Xaml)을 주로 수정해가며 프로그램을 작성하게 됩니다.


One More Thing!!!!!!!!



타이핑이 번거로우신 분들을 위해 코드조각을 준비했습니다.
코드조각이란 코드를 쫌만 입력하고 Tab키를 누르면 코드가 자동완성되는 기능인데요. 예를들면 
VisualStudio의 코드 편집창 에서 for를 입력하고 Tab키를 2회 눌러보면 

이런 코드가 나타납니다.
커서는 i에 가있고요, i를 j등으로 수정하고 Tab을 누르면 length로 갑니다. length를 원하는 수로 변경하고 엔터를 누르면 {와 } 사이로 커서가 이동합니다.  겁나 편한거죠.

코드조각을 추가하려면


코드 조각 관리자에 액세스하려면

  • 도구 메뉴에서 코드 조각 관리자를 클릭합니다.


코드 조각을 코드 조각 관리자로 가져오려면

  1. 언어: 드롭다운 목록에서 코드 조각을 추가할 언어를 선택합니다.

  2. 가져온 코드 조각을 넣을 기존 폴더를 선택합니다.

  3. 가져오기를 클릭합니다. 코드 조각 디렉터리 창이 열립니다.

  4. 코드 조각 관리자에 추가할 코드 조각을 선택한 다음 확인을 클릭합니다. 이제 코드 편집기에 이 코드 조각을 삽입할 수 있습니다.

참조:(MSDN) http://msdn.microsoft.com/ko-kr/library/vstudio/9ybhaktf(v=vs.100).aspx

4개의 코드조각을 올려놓겠습니다.

prop.snippet


프로퍼티입니다.

prop 만 입력하시고 Tab을 2회 입력하시면 이렇게 뜰겁니다.
제가 2회에 말씀드린거처럼 소문자로 시작하는 변수이름, 대문자로 시작하는 프로퍼티 이름, 그리고 변수타입 만 입력해주시면 됩니다.


cprop.snippet


그 다음은 아직 사용해본 적 없는 컬렉션 입니다.
cprop까지 입력하시고 Tab을 2회 입력하시면 이렇게 뜹니다.
역시 Tab을 이용해서 소문자로 시작하는 변수이름, 대문자로 시작하는 프로퍼티 이름, 변수타입만 입력해 주시면 됩니다.


이번엔 Command 입니다.
앞에 2회에서 사용하긴 했는데요, 저희 회사에서는 2가지 타입의 Command를 사용합니다.
먼저 cmd라고 입력하시고 Tab을 2회 입력하시면 
이렇게,

cmda라고 입력하시고 Tab을 2회 입력하시면 
이렇게 나올껍니다.
마찬가지로 소문자로 시작하는 커맨드 변수 이름과 대문자로 시작하는 커맨드프로퍼티? 이름만 바꿔주시고 Name()이라고 되어있는(이름은 바뀌겠죠?)함수에 기능을 구현하면 됩니다.

두가지 Command의 차이는 Can으로 시작하는메소드가 있고, 없고의 차이입니다.
어떤상황이던지 전부 실행 가능한 Command(예를들어 Close같은?)는 Can으로 시작하는 메소드가 따로 필요없겠죠.
그럴때 사용합니다.  

자....... 이제 준비는 다 된거 같습니다.
이제 열심히 달려서 우리의 동내북 "드럼 달땡"님의 툴을 완성해 봅시다!
다음번엔 컬렉션을 사용해보겠습니다.



움허허허!



Posted by zinzza
내가 아는거/WPF2012. 11. 19. 15:25


Apparelbase.MVVMBase.dll


안녕하세요 zinzza, 연두父, 이경배입니다.

2회입니다. 이번엔 지난번에 이어 MVVM의 장점을 이해하기 위해 또 한번 삽질의 시간을 갖고자 합니다.

하지만 이번걸 이해해야 다음 진행이 가능할거 같습니다.


C&P 한거지만... 다시한번 대상설명을 드리자면^^;;;


이 글의 대상은 엄청 간단한 C#책을 살짝쿵 읽어본 기획자, 대학, 학원등에서 C#프로그램을 좀 배운 수준의 사람들을 대상으로 적었습니다.


일단... 프로그래머 분들께서는 이 글의 오류를 찾아 저에게 제출해주시고, 그럴 목적이 아니시라면 읽지 말고 나가주세요.(부끄로아요ㅜㅜ)


아... MVVM의 장점 하나 설명하려고 별별 삽질을 다 해봅니다.
그럼 지난번에 만든걸 MVVM패턴으로 만들어보겠습니다.




먼저 새 프로젝트를 만들어봅시다.
뭐... 다 아는걸 괜히...^^;




그 다음엔 제가 첨부해 놓은 Apparelbase.MVVMBase.dll을 참조에 추가합니다.


Apparelbase.MVVMBase.dll


* 방법은 솔루션 탐색기의 참조에서 오른쪽버튼-> 참조추가-> 찾아보기 에서 찾아 추가해주시면 됩니다.

MVVM패턴을 하기 위해서는 몇가지 특정 자료형을 사용해야 하는데 그 사용을 좀 편리하게 해주는 겁니다.  저희 회사에서 사용하는 것들 중 필요한것만 살짝 뺐습니다. 그래도 괜히 우리 팀 이름을 붙여 봤습니다^^;


그리고 MainWindow를 꾸며봅시다!




역시 껍대기는 간단하게 만들 수 있으니 스킵합니다.

자~ 그 다음엔 ViewModel을 추가 해야 합니다.
뷰는? MainWindow.xaml 이 뷰 입니다^^;
모델은? 이건 좀 나중에^^;

솔루션 탐색기의 프로젝트 이름에서 오른쪽버튼 -> 추가-> 클래스 

클래스 이름은 알아보기 쉽게 MainViewModel.cs 로 가죠. 

 MainViewModel.cs를 열어서 위의 빨간부분을 입력합니다.


using Apparelbase.MVVMBase; 는 아까 추가한 dll을 이 파일에서 사용하겠다는 뜻입니다.
public은... 여기저기서 쓸려고 걍 넣은겁니다. 일단 보안은 신경 안쓰니까 편하게^^;
:ObservableObject 는 뷰모델의 기본이 되는 프로퍼티들이 정의되어있습니다.(이게 dll안에 들어있던놈입니다.) 당장 몰라도 되니 그냥 넘어가죠^^;

자~ 이제 뷰모델을 만들었으니 이 안에 데이터를 제어하는 코드들을 넣어야 합니다.
아까 만든 Winform 보다 조금 복잡한 코드입니다.
음... 우선 TestNumber 변수를 하나 선언할까요?



헉!  이게 뭔가요?


이건 변수가 아니고 프로퍼티라고 하는겁니다.  더 자세히 말씀드리면 의존프로퍼티(Defendency Property) 라고 하는거죠. 복잡한가요? 차근차근 보면 뭐^^;;




다시 한번 MVVM에 대한 그림을 보시면 Properties라는 부분이 있을껍니다.
바로 그 Property중에 하나를 선언한겁니다^^;

MVVM에서는 Property가 변하면 View에 자동으로 반영됩니다. 이거 꽤 편해요!
이번화에서는 Properties와 ICommands 를 사용할껍니다.

아! 프로퍼티에 대해서 알고 계시면 3-2의 빨간 글씨만 보시고 넘어가셔도 무방합니다.

1. 먼저 노란 #region은 신경 안쓰셔도 됩니다. 그냥 여기서부터 여기까지 TestNumber에 대한 내용이다~ 라는거고 프로그램에는 아무 역할도 안하는놈입니다.
2. 소문자로 시작하는(습관입니다)testNumber 변수는 실제 값을 저장하는 변수입니다.
3. public 으로 선언되고 대문자로 시작하는 TestNumber 가 바로 의존프로퍼티인데요
사실 이 MainViewModel을 외부에서 접근할때는 testNumber로 접근하는게 아니고 TestNumber를 통해 값을 설정하고 조회합니다.
TestNumber에는 testNumber를 설정, 조회하는 방법을 정의하는거죠.
그래서! get과 set 을 갖고 있습니다.
3-1 get은 간단하니 먼저 설명합니다.
그냥 return this.testNumber; testNumber의 값을 바로 읽는겁니다.(왜 이런 삽질을...ㅎㅎ 천천히 아셔도 됩니다. )
3-2 set 역시 this.testNumber = value; 로 TestNumber에 설정되는 값을 바로 testNumber에 지정합니다.
하지만 코드가 2줄 더 있는데요, if를 통해 같은 값인 경우 다시 지정하지 않게 하는 코드 한줄,
그리고 this.RaisePropertyChanged(“TestNumber”); 를 잘 기억해 두시기 바랍니다.
“나 변했어요~~~” 하고 프로그램한테 알려주는 메소드입니다.

음... 위 내용이 복잡하시면
변수를 선언할때 위 형태를 유지해 주시고 testNumber, TestNumber, int  이 3가지만 필요에 맞게 변형해서 사용하시면 됩니다.(저도 처음엔 그렇게 했어요)

자 이제 이걸 컨트롤 하는 ICommands를 만들어봅시다.
아! ICommand를 추가하기 전에 MainViewModel 위쪽에 using System.Windows.Input;  을 추가 해 줘야 합니다. ICommand가 여기 있거든요.
이제 추가해줍시다!


으악!!


복잡하지만 정 귀찮으시면 이번 역시 plus와 Plus 만 이름에 맞춰 바꿔쓰시면 됩니다.

물론 설명도 해야겠죠 ㅜㅜ
1. 먼저 소문자로 시작하는(역시나 습관) plusCommand 를 하나 선언하고요,
2. 대문자로 시작하는 PlusCommand를 하나 선언합니다.
get 구현하되 형식을 유지하고 그냥 plus와 Plus 부분만 수정한다고 기억하세요. 자세한 설명은 생략합니다.(너무 길어져요 ㅜㅜ)
3. CanPlus() 는 이 ICommand가 실행 가능한 상황인지 아닌지를 판단하는 메소드 입니다. 뒤에 다시 설명할꺼고요, 지금은 무조건 true를 반환하게 되어있습니다.
4. Plus() 메소드에 진짜 필요한 코드가 들어가는겁니다. 아... 이 간단한거 한줄 넣으려고 이게 뭔 짓입니까 ㅜㅜ?

마찬가지로 마이너스 커맨드도 만들어야겠죠?




뭐... plus, Plus 를 minus, Minus로 바꾼거 와 ++가 --로 바뀐거 말고는 달라진게 없군요.
암튼 이제 ViewModel을 다 만들었습니다! 실행!!!!!!!!!!! F5!!!!!!!!!!!!!!!





















.

.

.




.

.

.

.

.

.

.




































.

.

.

.

.

.

.

.

.

.

.

.

.

.














허허... 안되네....



왜 안될까요? 그건 View랑 ViewModel을 연결해주지 않았기 때문입니다.


솔루션 탐색기에서 MainWindow.xaml.cs를 선택해 줍니다.




그리고 연결하는 코드를 넣어주죠.



한줄만 넣어주시면 됩니다.  이 뷰의 뷰모델은 MainViewModel이다~ 라는 뜻이죠.

다시 MainWindow.xaml 파일을 열어서 마치 html코드 처럼 생긴 xaml코드를 봅니다.



저는 보기 편하게 하려고 Enter를 좀 쳐놔서 모양이 다를껍니다.
아마 한줄에 죽~ 나오실꺼에요.
순서대로 갑니다~
1. 먼저 Label의 Content를 “{Binding TestNumber}” 라고 수정해줍니다. - ViewModel의 TestNumber 프로퍼티를 연결한겁니다.
2. + Button에 Command="{Binding PlusCommand}" 를 추가 해 줍니다. - ViewModel의 PlusCommand ICommand를 연결한겁니다.
3. - Button에 Command="{Binding MinusCommand}" 를 추가 해 줍니다. - ViewModel의 MinusCommand ICommand를 연결한겁니다.




이렇게요^^;

아~~~~ 정말 수고하셨습니다~~~~ 이제 진짜로 F5!
실행을 확인합니다.
정말... Winform에서 간단하던 걸 왜 이 고생을 한 건지 이해가 안됩니다.


아~이해안되~~

자... 이제 거의 다 왔습니다.

앞에Winform에서 했던 3번의 수정을 더 하면 끝인거죠-_-??????????



또....-_-?



ㅎㅎㅎ 그레도 MVVM은 수정이 좀 쉬우니까요- 그래서 쓰는 거라니깐요^^;
자... 처음이 뭐였죠?
Label을 TextBox 로 변경?

해보죠 뭐.



MainWindow.xaml 파일에서 Label 을 TextBox로 수정하고 Content를 Text로 수정해주세요.(TextBox에는 Content라는 속성이 없고, Text라는 프로퍼티가 있거든요)
끗!

그 다음은 뭐였죠?
아... 0미만으로 내려가지 않기, 10초과해서 올라가지 않기였죠?
그럼 이번엔 MainViewModel의 TestNumber 프로퍼티를 보시죠.  
값을 지정하는거니까 set 부분을 수정해줘야 합니다.
if (this.testNumber != value) 부분을
if (this.testNumber != value && value >= 0 && value <= 10) 으로 수정해주세요.



0보다 작거나 10보다 큰 값은 아예 testNumber에 지정되지 않게 됩니다.
끗!

자~ 그 다음!
아! 버튼 비활성화였죠?
0일때10일때...
이번엔 PlusCommand와 MinusCommand에서 CanPlus, CanMinus 메소드를 수정해야 할 시점입니다.
CanPlus메소드에서
if (true) 를 if (this.TestNumber<10) 으로 고쳐주세요.



CanMinus메소드에서
if (true) 를 if (this.TestNumber>0) 으로 고쳐주세요.




각 커맨드가 조건에 의해서 실행되고 안되고를 지정해주는건데요, 이렇게만 해주면 버튼이 조건에 의해 자동으로 활성화, 비활성화됩니다.(오옷!)

끗!

자~~~~~ 마지막! 이름 변경!
각 컨트롤들의 Name 속성을 바꿔주세요.
코드는 바꾸실 필요 없습니다^^;(이름으로 연결된게 아니라 값 자체가 연결(Binding 된거)니까요)
끗!

아... 만들때는 좀 힘들었지만(사실 설명이 힘들고 익숙하지 않은거죠, 이텔릭체로 써놓은 것처럼 그냥 규칙대로 쓰고,  크게 어렵지도 않아요. 타이핑이 많을 뿐.)





아무튼..저는 힘들었어요.

이렇게 MVVM 패턴은 유지보수, UI수정등을 쉽게 할 수 있다는 장점을 갖고 있느 패턴입니다.
자... 아무튼 일단 MVVM과 WPF와 C#과 XML을 이용해서 우리 놀개영의 공식 동내북 달땡님이 원하는 툴을 함 만들어 보겠습니다!
고고고!




Posted by zinzza
내가 아는거/WPF2012. 11. 19. 15:20

안녕하세요 zinzza, 연두父, 이경배입니다.

오랫만에 글을 적어봅니다.

글을 적는 시점에서 제 계획은 C#으로 게임에 응용될 간단한 툴을 제작해보려고 합니다.


이 글의 대상은 엄청 간단한 C#책을 살짝쿵 읽어본 기획자, 대학, 학원등에서 C#프로그램을 좀 배운 수준의 사람들을 대상으로 적었습니다.


일단... 프로그래머 분들께서는 이 글의 오류를 찾아 저에게 제출해주시고, 그럴 목적이 아니시라면 읽지 말고 나가주세요.(부끄로아요ㅜㅜ)


그 시작은...



시작.


그리고 강의에서 만들려고 하는 툴은 이러하지요.


학습목표.


목표는 이러합니다.


이걸... WPF와 XML과 C#을 이용해서 만들려고 합니다. MVVM패턴으로요^^;
천~천~히(달땡님 미추어버리게)

MVVM이란?
뭐든지 정의를 찾아야 할때는 만든놈들한테 물어봐야 합니다.
http://msdn.microsoft.com/ko-kr/magazine/dd419663.aspx#id0090006
Microsoft에 나와있는 MVVM에 대한 정의.


주의!
위 내용을 읽으려고 시도하던 중 뭔 소린지 모르겠다 할때는 일단 읽는 것을 중단하고 아래로 진행해야 합니다.  저걸 이해하겠다고 사전찾고 MVC, MVP 등... 모르는 것들의 정의를 찾아 여행여행 하다보면... 똑똑해집니다-o-;
하지만 저는 위의 내용들을 이해하려고 하다가 포기하게 되더군요. 





그레서 전 포기하는것보다 “모르고 마구자비로 하다보니 알게되었다” 의 테크를 추천합니다. 사실... 저도 잘 모르는게 많고요 ㅜㅜ

내가 생각하는 MVVM
그레도 아예 모르고 넘어가는 것 보다는 조금이라도 알 수 있게... 제가 이해하고 있는걸 풀어보겠습니다. 이것까지 모르겠으면 또 넘어가 봅시다.

MVVM은 프로그램을 개발할때 Model 과 View와 ViewModel을 나눠서 개발하자는 뜻입니다.
그림으로 볼까요?


출처:
http://openlightgroup.net/Blog/tabid/58/EntryId/84/Silverlight-MVVM-The-Revolution-Has-Begun.aspx

오~~ 설명이 잘 되어있는 이미지군요.
(이미지 안에 있는 UI, Collections,...Web Services등은 무시하세요. 나중에 나중에^^)

해석이 다를 수 있지만 제가 생각하는 단어로 매칭을 좀 해보면
Model은 데이타, 자료 등으로 해석할 수 있을거 같습니다.
View는 UI정도로 해석해볼까요?
ViewModel은... 글쎄요-_-??? 그냥 뷰모델이죠 뭐.(데이타를 제어하는 로직, 화면에서 내려지는 명령 처리등이 들어갑니다)



저도 잘 모른다니깐요ㅜㅜ


반복하는 거지만 MVVM은 위 그림처럼 프로그램에서 UI와 데이터, 로직을 분리하겠다는 뜻입니다.

그나저나 왜 나누냐구요-_-?
이유는 이런 상황에 대처하기 위해서 입니다.
일반적인? Winform에서는 뷰를 제어하는 코드가 직접 들어가죠.
예를들어 텍스트박스에 글자를 넣기 위해서는...
form1.txtName = “연두부”;
이런 코드 말이죠.
만약에 위 코드에서 텍스트박스를 label로 바꾼다면요? 그 label을 또 다시 TextBox으로 바꾼다면?
뷰는 당연히 바꾸는거고,  모든 소스코드를 뒤져가며 txtName을 lblName으로 또 txtblockName등으로 바꿔줘야 합니다.(뒤에 간단한 실습으로 한번 보여드리겠습니다.)
물론 Ctrl + H는 저도 잘 알고있습니다만... 어느정도 규모가 되는 프로그램이라면 그것도 보통 일은 아니죠-_-;
이런 문제를 해결하는 방법으로 MVC라는 패턴이 생겨났고, MVC의 파생된 형태라고 생각하면 됩니다.
그럼 어떻게 나누냐구요-_-?
그건 좀 있다가^^;

뭐 그림으로도 설명은 잘 안되는군요-_-;
일단 막 진행해 볼까요?
하다보면 되겠죠 뭐~ 안되서 질문이 올라오면 업데이트도 좀 하고... ㅎ

왜 MVVM인가?
여러가지 장점이 있지만 가장 큰 이유는...
개발자가 WPF와 MVVM에 익숙해진 뒤에는 이 둘을 차별화하기가 어려워집니다.(msdn)
때문입니다.
제가 회사에서 거의 대부분의 프로젝트를 MVVM패턴을 이용하거든요.
실제로 MVVM에 익숙해진 다음 WinForm프로그래밍을 하면 짜증이 밀려오는 재미있는 경험을 하게됩니다.





그럼 직접 그 짜증을 경험해봅시다.
C#으로 간단하게 화면에 숫자를 표시하고 “+”버튼을 누를때마다 숫자가 증가하고, “-”버튼을 누를때마다 숫자가 감소하는 프로그램을 만들어봅시다.

일반적인 윈폼으로 말이죠^^;



먼저 폼을 디자인합니다. label 하나와 button 2개로 구성합니다.
이부분은 자세히 설명하지 않겠습니다.
그리고, 버튼의 크기다 다르고 디자인이 구린건 님들 모니터가 불량인겁니다.
자 그럼 + 버튼과 -버튼을 더블클릭해서 소스를 입력합시다.




1. 숫자변수 TestNumber를 선언했습니다.
2. + 버튼의 코드입니다.
3. -버튼의 코드입니다.

자... 이젠 문제점을 파악해야 하니 이 프로그램의 label을 textbox로 변경해보겠습니다.



자... 이렇게 label을 지우고 textbox를 올려놨습니다.




오호라... 역시나 에러가뜨는군요.
위의 label1을 textbox1이라고 바꿔주면 일단 정상적으로 돌아갑니다^^;

이왕 하는거 좀 더 가보죠.
최대값은 10, 최소값은 0으로 지정해서 0이 되면 -버튼을 눌러도 숫자가 변하지 않게 해보는겁니다.
+버튼도 마찬가지로 10 이상 증가하지 않게^^;




오~~~ 점점 코드가 늘어가는군요. 복잡해요.

하나만 더 해봅시다.
이번엔 0일때 -버튼이 비활성화, 10일때 +버튼이 비활성화 되는겁니다.

사실 0일때 -버튼을 누를 일이 없으니까요.^^;




자 저는 CheckButtonEnable() 이라는 함수를 하나 만들어서 두 버튼 이벤트에 추가해줬습니다.

ㅎㅎㅎ 이제 One more thing!
프로그램을 요모냥으로 짰더니 누군가 와서 이렇게 말합니다.
“야 인간아~ button1이 뭐냐? 당장 txtNumber, btnPlus, btnMinus로 바꿔!” 라고 말이죠.




정신차리고 뭘 해야 할지... 생각 좀 해봅시다. 뭘 해야하지-_-?

1. 일단 뷰에 가서 컨트롤들의 이름을 변경합니다.
2. 이벤트 이름이 바뀝니다. 그럼 각 버튼 이벤트에 있는 코드를 복사해서 새로 생긴 btnPlus_Click , btnMinus_Click 이벤트쪽으로복사합니다.
3. 코드에서 textbox1 로 되어있는 코드들을 전부 txtNumber로 변경합니다.
4. 코드에서 button1로 되어있는 코드들을 전부 btnPlus로 변경합니다.
5. 코드에서 button2로 되어있는 코드들을 전부 btnMinus로 변경합니다.


안해-o-!



이 연두 코딱지만한 프로그램에서 할일이 이따위로 많은데 실제로 회사에서 하는 프로젝트면... 에효...


그리하야!

이런 문제를 해결하고자 MVVM을 사용합니다!!! 

다음번엔 똑같은 짓을 MVVM패턴으로 해봅니다. ㅎㅎㅎㅎ


그럼 다음시간까지~ 안녕~~~



Posted by zinzza