ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Silverlight3 - Binding
    Silverlight 2009. 5. 3. 09:46

    지난 글에서 Silverlight 3에 새롭게 추가된 3D 기능에 대해서 알아봤습니다. 이번에는 Silverlight 2보다 기능이 더욱 강화된 Silverlight 3의 Binding에 대해서 알아보겠습니다.

    들어가기에 앞서..
    Silverlight 3에서 강화된 Binding 기능은 Silvelight 2의 기능에 Element binding과 Binding validation이 추가되었습니다. 이 글에서는 Silvelight 3에 추가된 기능만을 살펴볼 것이기에 Silverlight 2의 Binding에 대한 기본 지식이 필요합니다. 이 부분에 대해 이해가 필요하신 분들은 공도님이 올려주신 아티클(http://gongdo.tistory.com/390) 1편과 2편을 먼저 보시길 추천 드립니다.
    그리고 새롭게 강화된 Binding 기능은 이미 WPF에서는 제공되던 기능이기에 WPF의 Binding을 알고 계시면 수월하게 이해하실 수 있습니다 ^^

    Element binding 
    Silverlight 3에서 추가된 Element 바인딩을 사용하기 위해서 다음과 같이 ElementName 프로퍼티를 추가해주면 됩니다. ElementName 프로퍼티에 할당되는 값은 바인딩 할 타깃 Element의 이름을 의미합니다. 그럼 ElementName 프로퍼티를 어떻게 사용 하는지 알아보기 위해 사용자가 Slider를 조절하면 Rectangle 사이즈를 조절하는 간단한 예제를 살펴보겠습니다.

    XAML

    <Grid x:Name="LayoutRoot">
            <Grid>
                <Rectangle x:Name="_Rect"
                           Fill="Teal" Width="100" Height="100"
                           HorizontalAlignment="Center" VerticalAlignment="Center"/>
                <Slider
                    Width="200"
                    HorizontalAlignment="Center" VerticalAlignment="Bottom"
                    Minimum="100" Maximum="400"
                    Value="{Binding Width, ElementName=_Rect, Mode=TwoWay}"/>
            </Grid>
        </Grid>


    위의 XAML을 살펴보면 Rectangle(이름: _Rect)의 Width를 Slider의 Value와 Binding한 것을 확인할 수 있습니다.
    다음 프로그램은 위 예제를 실행시킨 것으로, 한 줄의 C# 코드도 사용하지 않고 2개의 Element가 손쉽게 Binding 된 것을 확인할 수 있습니다.
    Silverlight 2에서는 ElementName 프로퍼티가 지원되지 않기 때문에 다음과 같은 예제를 구현하기 위해서는 C# 코드가 필요했었습니다.

    Get
    < 예제 >


     

    ValidatesOnExceptions
    바인딩 validation을 설명하기 위해 다음과 같이 간단한 예제를 먼저 작성해 보겠습니다.

    C#

    public class Person
        {
            private string name;
            public string Name {
                get
                {
                    return name;
                }

                set
                {
                    if (name.Length >= 5)
                        throw new Exception("이름은 5자 미만으로 입력해주세요.");

                    name = value;
                }
            }

            private int age;
            public string Age {
                get
                {
                    return age;
                }

                set
                {
                    if (age > 100)
                       throw new Exception("나이는 100살 미만으로 입력해주세요.");

                    age = value;
                }
            }
        }


    데이터 바인딩을 하기 위해 Person 클래스를 하나 만들었습니다. Person 클래스는 사람을 나타내며 이름(Name)과 나이(Age)를 가지고 있습니다. 그리고 코드에서 강조한 것처럼 이름의 길이가 5를 넘어가면 예외(Exception)을 발생시키도록 했습니다. 나이 역시 100 이상을 입력하면 예외를 발생시켰습니다. Silverlight 2 같은 경우에는 이렇게 예외를 발생시켜도 아무런 예외 처리를 하지 않고 그냥 예외가 사라지는 현상이 발생합니다. 하지만 Silverlight 3에서는 다음에 나오는 XAML과 같이 ValidatesOnExceptions 프로퍼티를 True로 설정함으로써 바인딩 에러가 났음을 화면에 표시할 수 있습니다.

    XAML

    <Grid x:Name="LayoutRoot">
            <Grid.RowDefinitions>
                <RowDefinition Height="30"/>
                <RowDefinition Height="30"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="100"/>
                <ColumnDefinition Width="150"/>
            </Grid.ColumnDefinitions>
            <TextBlock
                VerticalAlignment="Center"
                Grid.Row="0" Grid.Column="0"
                Text="Name"/>
            <TextBox
                VerticalAlignment="Center"
                Grid.Row="0" Grid.Column="1"
                Name="_Name" Text="{Binding Name, Mode=TwoWay, ValidatesOnExceptions=True}"/>
            <TextBlock
                VerticalAlignment="Center"
                Grid.Row="1" Grid.Column="0"
                Text="Age"/>       
            <TextBox
                VerticalAlignment="Center"
                Grid.Row="1" Grid.Column="1"
                Name="_Age" Text="{Binding Age, Mode=TwoWay, ValidatesOnExceptions=True}"/>
        </Grid>


    XAML 파일은 TextBox에 Name과 Age를 바인딩하고 있습니다. 그리고 ValidatesOnExceptions 프로퍼티를 설정했습니다.


    C#

    public partial class MainPage : UserControl
        {
            public MainPage()
            {
                InitializeComponent();

                Loaded += new RoutedEventHandler(MainPage_Loaded);
            }

            void MainPage_Loaded(object sender, RoutedEventArgs e)
            {
                Person person = new Person("Sirius", 10);

                LayoutRoot.DataContext = person;
            }
        }

    메인 C#에서는 페이지가 로드 되면 데이터 Binding을 위해 DataContext에 Person 인스턴스를 할당해주고 있습니다.

     

    위 화면은 Age에 102를 입력한 결과입니다. 위 코드에서 본 것처럼 Age가 100을 넘으면 Exception을 발생시켰습니다. 그리고 바인딩 한 곳에 ValidatesOnExceptions 프로퍼티를 True로 설정해준 결과 위 화면과 같이 Exception에서 발생시킨 내용이 나오게 되는 것입니다. TextBox는 기본적으로 바인딩 중 예외가 발생하면 위 그림과 같이 빨간 사각형 경고 창으로 알려주게 되어있습니다.

    Get
    < 예제 >

     


    Validation class
    Silverlight 3에는 데이터 바인딩의 검증을 위해서 Validation 클래스가 새롭게 추가되었습니다. Validation  클래스는 다음과 같이 2개의 프로퍼티와 2개의 메서드를 가지고 있습니다.

      

     
    HasErrorProperty와 ErrorsProperty는 Attached Property로 되어 있어 다른 엘리먼트에 추가할 수 있는 구조로 되어 있습니다. 위에서 살펴봤던 예제처럼 바인딩 에러가 발생하면 바인딩 에러가 발생한 엘리먼트에 HasErrorProperty와 ErrosProperty가 추가되는 것입니다.
    GetErrors()와 GetHasError() 메서드는 앞서 설명한 프로퍼티들을 쉽게 구할 수 있도록 도와주는 헬퍼(Helper) 메서드 입니다. GetHasError() 메서드는 엘리먼트에 HasErrorProperty가 설정되어 있으면(즉, 바인딩 에러가 발생한 경우겠지요?) True를 리턴 해서 해당 엘리먼트가 바인딩 에러를 가지고 있음을 알려주는 역할을 합니다. GetErrors() 메서드는 엘리먼트가 바인딩 에러를 가지고 있다면 엘리먼트에 발생한 ValidationError 클래스의 인스턴스를 구해서 구체적인 에러 내용을 살펴볼 수 있도록 해줍니다.
    그럼 구체적으로 어떻게 Validation 클래스를 사용하는지 알아보기 위해 간단한 회원 가입 폼의 예제 코드와 샘플을 살펴보겠습니다.

    Get
    < 예제 >

    C#

    public class Person
        {
            public Person(string id, string name, int age)
            {
                this.id = id;
                this.name = name;
                this.age = age;
            }

            private string id;
            public string ID
            {
                get
                {
                    return id;
                }

                set
                {
                    if (value.Length >= 10)
                        throw new Exception("ID은 10자 미만으로 입력해주세요.");

                    id = value;
                }
            }

            private string name;
            public string Name {
                get
                {
                    return name;
                }

                set
                {
                    if (value.Length >= 5)
                        throw new Exception("이름은 5자 미만으로 입력해주세요.");

                    name = value;
                }
            }

            private int age;
            public int Age
            {
                get
                {
                    return age;
                }

                set
                {
                    if (value > 100)
                        throw new Exception("나이는 100살 미만으로 입력해주세요.");

                    age = value;
                }
            }
        }


    위 Person 클래스는 앞에서도 사용했던 내용과 동일합니다. 단지 회원 가입 폼에서 사용하기 위해 ID 필드를 하나 추가하였습니다.

    XAML

    <Grid x:Name="LayoutRoot"
              >
            <Grid.RowDefinitions>
                <RowDefinition Height="30"/>
                <RowDefinition Height="30"/>
                <RowDefinition Height="30"/>
                <RowDefinition Height="30"/>
            </Grid.RowDefinitions>

            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="100"/>
                <ColumnDefinition Width="150"/>
            </Grid.ColumnDefinitions>
            <TextBlock
                VerticalAlignment="Center"
                Grid.Row="0" Grid.Column="0"
                Text="ID"/>
            <TextBox
                VerticalAlignment="Center"
                Grid.Row="0" Grid.Column="1"
                Name="_ID" Text="{Binding ID, Mode=TwoWay, ValidatesOnExceptions=True}"/>

            <TextBlock
                VerticalAlignment="Center"
                Grid.Row="1" Grid.Column="0"
                Text="Name"/>
            <TextBox
                VerticalAlignment="Center"
                Grid.Row="1" Grid.Column="1"
                Name="_Name" Text="{Binding Name, Mode=TwoWay, ValidatesOnExceptions=True}"/>

            <TextBlock
                VerticalAlignment="Center"
                Grid.Row="2" Grid.Column="0"
                Text="Age"/>
            <TextBox
                VerticalAlignment="Center"
                Grid.Row="2" Grid.Column="1"
                Name="_Age" Text="{Binding Age, Mode=TwoWay, ValidatesOnExceptions=True}"/>
            <Button
                x:Name="RegisterButton"
                VerticalAlignment="Center" HorizontalAlignment="Center"
                Grid.Row="3" Grid.Column="1"
                Content="회원 가입"
                Click="RegisterButton_Click"
                />
        </Grid>

    XAML 파일은 회원의 ID, 이름, 나이를 입력 받을 수 있게 구성했습니다. 그리고 ID, Name, Age를 바인딩  했으며, ValidatesOnExceptions 프로퍼티를 True로 설정했습니다.
    그리고 회원 가입 버튼을 하나 추가해서 이 버튼을 누르면 RegisterButton_Click 메서드가 호출되도록 했습니다. 이 메서드가 이번에 설명할 가장 중요한 부분으로 각 필드를 Validation 클래스를 이용해 검증하는 역할을 합니다. 자세한 설명은 다음 C# 코드에서 하도록 하겠습니다.

      * Validation 클래스를 사용하기 위해서는 ValidatesOnExceptions 프로퍼티가 필히 True로 설정되어 있어야 합니다.

    C#

    public MainPage()
    {
        InitializeComponent();

        Loaded += new RoutedEventHandler(MainPage_Loaded);
    }

    void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        Person person = new Person("antasis9", "Sirius", 10);

        LayoutRoot.DataContext = person;
    }

    private void RegisterButton_Click(object sender, RoutedEventArgs e)
    {
        string errorMessage = "";

        // ID 필드 체크
        if (Validation.GetHasError(_ID))
        {
            errorMessage = "[ID 필드]\n";
            errorMessage = Validation.GetErrors(_ID)[0].Exception.Message;
        }

        // Name 필드 체크
        if (Validation.GetHasError(_Name))
        {
            errorMessage += "\n\n[Name 필드]\n";
            errorMessage += Validation.GetErrors(_Name)[0].Exception.Message;
        }

        // Age 필드 체크
        if (Validation.GetHasError(_Age))
        {
            errorMessage += "\n\n[Age 필드]\n";
            errorMessage += Validation.GetErrors(_Age)[0].Exception.Message;
        }

        MessageBox.Show(errorMessage);
    }

    C# 코드는 MainPage가 로드 되면 데이터 바인딩을 위해 Person 객체를 생성해 DataContext에 할당해 주는 역할을 합니다. 그리고 RegisterButton_Click 메서드는 앞서 설명했던 회원 가입 버튼을 누르면 호출되는 메서드로 각 필드를 체크하는 역할을 합니다. 처음으로 Validation.GetHasError 메서드를 사용해 ID 필드를 체크합니다. 만약 바인딩 에러가 존재한다면 errorMessage에 에러 내용을 추가합니다. 이런 식으로 Name, Age필드도 체크하고 에러가 있으며 errorMessage에 에러 내용을 추가한 후 메시지 박스를 이용해 화면에 에러 내용을 출력합니다.
    이처럼 Validation 클래스는 C# 코드를 이용해서 바인딩 에러를 처리할 수 있도록 도와주는 역할을 합니다.

    마치며..

    이상으로 Silverlight 3에서 강화된 Binding 기능을 살펴보았습니다. Silverlight 2에서는 Element 사이의 바인딩을 xaml에서 할 수 없었지만 3에서 추가된 강화된 바인딩을 이용해 손쉽게 추가 코드 없이 바인딩을 할 수 있게 되었습니다. 이러한 기능은 디자이너가 코드 없이 바인딩 할 수 있도록 도와줍니다. 이상으로 부족한 글이지만 도움이 되었으면 좋겠습니다~ ^^

Designed by Tistory.