본문 바로가기

C#의 속삭임

[C#][WPF][프레임워크][MVVM] MVVM Light

* 비쥬얼 스튜디오에 WPF가 있었다. 문득 궁금해졌다. 그래서 찾아 보았다.

** 실버라이트 기반으로 만든 어플리케이션 어쩌구 저쩌구..라고 그런다; 중요한것은 이것이 아니다. 실버라이트랑 비슷한 개발 형태를 뛴다는 것은 중요하다. 즉, 개발시 디자이너파일이 따로 분리 되어 있다.

** 웹개발자들은 MVC에 익숙하다. 하지만 이벤트 기반의 어플리케이션은 MVC로 분리는 말이 맞지가 않다. 그렇다 이벤트 기반의 어플리케이션 개발시 사용하는 패턴이 MVVM이다.

** 물론 다른 패턴도 있겠지만 아무튼 이렇다는게 중요하다.

** 그래서 MVVM에 대해서 공부하다 보니 여러개가 나온다. MVVM, Command, Behavior 이래 용어가 나온다. 그래 이게 중요한다.



* MVVM Light Toolkit 이란?

** 프레임워크이다. MVVM 패턴을 준수하여 개발된 프레임워크이다. 

** 다운로드 URL : http://www.galasoft.ch/mvvm/



* 디자이너는 어떻게 작업을 하나?

** 비주얼 스튜디오 패키지에 보면은 Blend for Visual Studio가 있다 그것을 사용하여 개발하면 된다. 

** blend를 사용하여 view파일을 만들어 내면, 개발자는 ViewModel을 대응하여 만들어 내면 된다.

** blend4 sdk for wpf : http://www.microsoft.com/ko-kr/download/details.aspx?id=10801

** nuget : http://www.nuget.org/packages/Microsoft.Expression.Blend.SDK.WPF/4.0.0



* 간단한 예제 

** URL : http://sirars.com/tag/mvvm-light-toolkit/ 

*** 위에 분께서 아주 친절하게 잘 성명 하였다. 난 그것을 보고 그대로 만들었을뿐...(-_ㅡ)a


1. MVVM Light를 설치하고, 비주얼 스튜디오을 열고, MVVM Light WPF 프로젝트를 생성합니다. ViewModel 폴더를 보면은

ViewModelLocator과 MainViewModel이 있는것을 볼수 있다. ViewModelLocator은 ViewModel들을 가지고 있다가 찾아 주는 역할을 한다. 즉 View에서 해당 ViewModelLocator을 보고, 선언 되어 있는 ViewModel을 찾아온다.

그럼 ViewModel을 생성해보겠다. "SenderViewModel" 클래스를 ViewModel폴더에 추가한다.

public class SenderViewModel : ViewModelBase

    {

        public RelayCommand OnClickCommand { get; set; }

        private string _textBoxText;


        public string TextBoxText

        {

            get { return _textBoxText; }

            set

            {

                _textBoxText = value;

                RaisePropertyChanged("TextBoxText");

            }

        }


        public SenderViewModel()

        {

            OnClickCommand = new RelayCommand(OnClickCommandAction, null);

        }


        private void OnClickCommandAction()

        {

            var viewModelMessage = new ViewModelMessage()

            {

                Text = TextBoxText

            };

            Messenger.Default.Send(viewModelMessage);

        }


    }


2. 여기서 만들 프로그램은 두개의 유저컨트롤이 String을 서로 주고 받아야 된다. 그렇게 하기위해 String을 주고 받아 줄 클래스를 작성 할것이다. 먼저, Messages라는 폴더를 추가한다. 그후, ViewModelMessage 클래스를 선언한다.

    public class ViewModelMessage : MessageBase

    {

        public string Text { get; set; }

    }


3. 자, 그럼 ViewModel에서 이벤트도 정의 되었으니 인제는 View를 만들어 보도록 한다. C#은 이벤트 프로그램을 기반을 두고 있다. 그러므로 화면단위로 분리 하는 것이 아니라, 컨트롤 단위로 보는것이 맞다. 그렇게 설계하는 것이 맞고, 가능할것이다. 그러므로 여기서 View라고 함은 컨트롤을 만드는 것이다. 즉 컨트롤+컨트롤=컨트롤 이렇게 만들기 위해, 먼저 UserControl을 생성 할 필요가 있다. View 폴더에 추가를 선택하여, SenderView라는 이름의 UserControl을 추가합니다. 그러면 XAML파일로 추가 됩니다. (XAML파일은 blend에서 편집이 가능합니다.)

<UserControl x:Class="Mvvm_Light.View.SenderView"

             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 

             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

             xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

             xmlns:Command="http://www.galasoft.ch/mvvmlight"

             mc:Ignorable="d" 

             d:DesignHeight="300" d:DesignWidth="300" DataContext="{Binding Source={StaticResource Locator}, Path=SenderViewModel}">

    <Grid>

        <Label Content="Sender" Margin="90,34,0,232"/>

        <TextBox HorizontalAlignment="Left" Width="120" Height="20" Margin="50,266,0,11" Text="{Binding TextBoxText}" Background="#FFDE8E8E"/>

        <Button Content="Send" Width="50" Height="25" Margin="183,265,67,10">

        <Button.Background>

        <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">

        <GradientStop Color="#FFF3F3F3" Offset="0"/>

        <GradientStop Color="#FFEBEBEB" Offset="0.328"/>

        <GradientStop Color="#FFDDDDDD" Offset="0.237"/>

        <GradientStop Color="#FF631C1C" Offset="1"/>

        </LinearGradientBrush>

        </Button.Background>

            <i:Interaction.Triggers>

                <i:EventTrigger EventName="Click">

                    <Command:EventToCommand Command="{Binding OnClickCommand}" />

                </i:EventTrigger>

            </i:Interaction.Triggers>

        </Button>

    </Grid>

</UserControl>

- 여기서 보면은 DataContext="{Binding Source={StaticResource Locator}, Path=SenderViewModel}"은 Locator을 통해 SenderViewModel과 연결 하는 것을 볼 수있습니다. 즉, UI만 가지고 있는 View와 이벤트를 가지고 있는 ViewModel과 연결 하는 것입니다. 


4. 그럼 MainWindow에 우리가 만든 View을 배치 해보겠습니다.

<Window x:Class="Mvvm_Light.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:view="clr-namespace:Mvvm_Light.View"

        Title="MainWindow" Height="350" Width="525">

    <Grid>

        <Grid.RowDefinitions>

            <RowDefinition Height="Auto" />

        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>

            <ColumnDefinition Width="Auto"/>

            <ColumnDefinition Width="Auto"/>

        </Grid.ColumnDefinitions>

        <view:SenderView Grid.Row="0" Grid.Column="1" Foreground="Black" Background="#FFBA33CF" />

        <GridSplitter HorizontalAlignment="Left" Width="5" Height="320" Margin="245,0,0,-21"/>

    </Grid>

</Window>


5. 인제 보내는 것은 끝났고 메세지를 받는 녀석을 만들겠습니다. 동일하게 ViewModel을 생성합니다. 이름은 ReceiverViewModel로 하겠습니다.

<UserControl x:Class="Mvvm_Light.View.ReceiverView"

             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 

             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 

             mc:Ignorable="d" 

             d:DesignHeight="300" d:DesignWidth="300" DataContext="{Binding Source={StaticResource Locator}, Path=ReceiverViewModel}">

    <Grid>

        <Label Content="Receiver" Margin="90,34,0,232"/>

        <Label Content="{Binding ContentText}" FontSize="20" Margin="65,255,40,0"/>

    </Grid>

</UserControl>


6. ViewModelLocator 에 ViewModel들을 바인딩합니다.

/*

  In App.xaml:

  <Application.Resources>

      <vm:ViewModelLocatorTemplate xmlns:vm="clr-namespace:Mvvm_Light.ViewModel"

                                   x:Key="Locator" />

  </Application.Resources>

  

  In the View:

  DataContext="{Binding Source={StaticResource Locator}, Path=ViewModelName}"

*/


using GalaSoft.MvvmLight;

using GalaSoft.MvvmLight.Ioc;

using Microsoft.Practices.ServiceLocation;

using Mvvm_Light.Model;


namespace Mvvm_Light.ViewModel

{

    public class ViewModelLocator

    {

        public ViewModelLocator()

        {

            ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);


            SimpleIoc.Default.Register<SenderViewModel>();

            SimpleIoc.Default.Register<ReceiverViewModel>();

        }


        public SenderViewModel SenderViewModel

        {

            get

            {

                return ServiceLocator.Current.GetInstance<SenderViewModel>();

            }

        }


        public ReceiverViewModel ReceiverViewModel

        {

            get

            {

                return ServiceLocator.Current.GetInstance<ReceiverViewModel>();

            }

        }


        public static void Cleanup()

        {

            // TODO Clear the ViewModels

        }

    }

}


7. 인제 View 컨트롤러를 생성합니다. 이름은 ReceiverView이고 폴더는 View폴더입니다.

<UserControl x:Class="Mvvm_Light.View.ReceiverView"

             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 

             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 

             mc:Ignorable="d" 

             d:DesignHeight="300" d:DesignWidth="300" DataContext="{Binding Source={StaticResource Locator}, Path=ReceiverViewModel}">

    <Grid>

        <Label Content="Receiver" Margin="90,34,0,232"/>

        <Label Content="{Binding ContentText}" FontSize="20" Margin="65,255,40,0"/>

    </Grid>

</UserControl>


8. MainWindow에 ReceiverView를 배치합니다.


<Window x:Class="Mvvm_Light.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:view="clr-namespace:Mvvm_Light.View"

        Title="MainWindow" Height="350" Width="525">

    <Grid>

        <Grid.RowDefinitions>

            <RowDefinition Height="Auto" />

        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>

            <ColumnDefinition Width="Auto"/>

            <ColumnDefinition Width="Auto"/>

        </Grid.ColumnDefinitions>

         <view:ReceiverView Grid.Row="0" Grid.Column="0" />

        <view:SenderView Grid.Row="0" Grid.Column="1" Foreground="Black" Background="#FFBA33CF" />

        <GridSplitter HorizontalAlignment="Left" Width="5" Height="320" Margin="245,0,0,-21"/>

    </Grid>

</Window>



9. 인제 빌드하시고, 실행하시면 됩니다. 위소스는 제가 짠것이 아니라 보고 따라한 소스 한국말로 적은 것입니다.

- 테스트 해보니 아주 잘 작동 하였으니 무난하게 잘 될것이라 생각됩니다. 

- C#이 처음인지라 신기하고 재미 있네요. 












'C#의 속삭임' 카테고리의 다른 글

[C#][WPF] 첫시작.  (0) 2014.04.23
[C#][WPF]데이터 바인딩  (0) 2014.04.22
[C#][패턴] MVVM  (0) 2014.04.16
[C#][AxWebBrowser] AxWebBrowser 컨트롤러  (0) 2014.04.08
[C#][WebBrowser] WebBrowser 컨트롤러  (0) 2014.04.04