Windows Phone의 데이터 바인딩

2013-12-05

적용 대상: Windows Phone 8 | Windows Phone OS 7.1

 

데이터 바인딩은 Windows Phone 앱에서 데이터를 표시하고 데이터와 상호 작용할 수 있는 간단한 방법입니다. 데이터 표시 방식은 데이터 관리 방식과 별개입니다. UI와 데이터 개체 사이에서 연결 또는 바인딩을 통해 데이터를 전달합니다. 바인딩을 설정한 후 데이터가 변경되면 데이터에 바인딩된 UI 요소는 변경 내용을 자동으로 반영합니다. 마찬가지로 사용자가 UI 요소를 변경하면 데이터 개체에 변경 내용이 반영될 수 있습니다. 예를 들어, 사용자가 TextBox의 값을 편집하면 해당 변경 내용을 반영하기 위해 내부 데이터 값이 자동으로 업데이트됩니다.

일반적인 바인딩 시나리오에는 헤드라인 목록에 ListBox 바인딩, 고객 데이터 개체에 입력 폼의 TextBox 바인딩, 현재 사용자 사진에 Image 바인딩 등이 있습니다.

이 항목에서는 간단한 코드 예제를 사용하여 데이터 바인딩 개념을 보여 줍니다. Visual Studio 을 사용하여 다양한 데이터 바인딩 작업을 수행할 수도 있습니다.

이 항목에는 다음 단원이 포함되어 있습니다.

 

모든 바인딩에는 소스와 대상을 지정해야 합니다. 다음 그림에서는 바인딩의 기본 개념을 보여 줍니다.

Explain Binding Details

소스는 대상 요소 자체 또는 다른 UI 요소를 비롯한 모든 CLR 개체일 수 있습니다. 대상이 데이터 템플릿에 있는 경우, 소스는 해당 템플릿이 적용되는 UI 요소일 수 있습니다.

대상은 FrameworkElement의 임의의 DependencyProperty가 될 수 있습니다.

대상은 다음과 같은 경우 DependencyObjectDependencyProperty일 수도 있습니다.

Windows Phone 8 이상에서 대상은 StyleSetterValue 속성일 수도 있습니다. 예제를 보려면 Style 클래스 개요를 참조하세요.

바인딩 엔진은 Binding 개체에서 다음에 대한 정보를 가져옵니다.

예를 들어 데이터에 따라 텍스트 색을 변경할 수 있도록 TextBoxForeground 속성을 SolidColorBrush에 바인딩할 수 있습니다. 이 시나리오에서 바인딩에 대해 Foreground 속성은 대상이며 SolidColorBrush 개체는 소스입니다.

다음 예제에서는 코드 및 XAML에서 TextBoxForeground 색을 SolidColorBrush로 바인딩하는 방법을 보여 줍니다. 바인딩 소스는 이 항목의 뒷부분에 설명되어 있는 MyColors 클래스의 속성입니다.


<TextBox x:Name="MyTextBox" Text="Text" Foreground="{Binding Brush1, Mode=OneWay}"/>



// Create an instance of the MyColors class 
// that implements INotifyPropertyChanged.
MyColors textcolor = new MyColors();

// Brush1 is set to be a SolidColorBrush with the value Red.
textcolor.Brush1 = new SolidColorBrush(Colors.Red);

// Set the DataContext of the TextBox MyTextBox.
MyTextBox.DataContext = textcolor;


참고참고:

이 예제에서는 바인딩을 만들기 위해 XAML 특성 구문을 사용합니다. XAML에서 바인딩을 만들기 위해 개체 요소 구문을 사용할 수도 있습니다. 자세한 내용은 Windows Phone용 XAML를 참조하세요.

바인딩은 XAML에서 {Binding ...} 구문을 사용하여 만듭니다. 소스는 코드에서 TextBoxDataContext 속성을 통해 설정됩니다.

데이터 컨텍스트는 상속됩니다. 부모 요소에 대해 데이터 컨텍스트를 설정하면 해당 자식은 모두 동일한 데이터 컨텍스트를 사용합니다. 자식 요소는 해당 바인딩 개체의 Source 속성을 설정하거나 해당 DataContext를 설정하여 이 동작을 재정의할 수 있습니다. 그러면 이 동작이 해당 자식에게 모두 적용됩니다.

데이터 컨텍스트 설정은 여러 바인딩에서 모두 동일한 소스를 사용할 경우 유용합니다. 단일 바인딩의 소스를 설정하려면 Binding 개체의 Source 속성을 설정합니다. 자세한 내용은 Windows Phone에 대한 데이터 바인딩을 만드는 방법를 참조하세요.

또한 ElementName 속성이나 RelativeSource 속성을 사용하여 바인딩 소스를 지정할 수 있습니다. ElementName 속성은 슬라이더를 사용하여 버튼 너비를 조정하는 경우처럼 앱의 다른 요소에 바인딩할 때 유용합니다. RelativeSource 속성은 ControlTemplate 또는 Style에서 바인딩을 지정할 때 유용합니다.

Binding.Path 속성을 설정하여 소스 개체의 속성에 바인딩할 수 있습니다. Path 속성은 중첩 속성, 연결된 속성, 문자열 인덱서에 대한 바인딩을 위한 다양한 구문 옵션을 지원합니다.

결과적으로 앞의 예제에서는 바인딩 엔진을 통해 기본적으로 OneWay인 바인딩을 만들고 TextBoxForeground 속성을 TextColor 개체의 brush1 속성에 연결합니다.

각 바인딩은 데이터 흐름 방식과 시기를 결정하는 Mode 속성을 사용합니다. Windows Phone 에서는 다음 세 가지 유형의 바인딩을 사용할 수 있습니다.

  • OneTime 바인딩은 바인딩을 만들 때 소스 데이터와 함께 대상을 업데이트합니다.

  • OneWay 바인딩은 바인딩을 만들어 데이터를 변경할 때 소스 데이터와 함께 대상을 업데이트합니다. 기본 모드입니다.

  • TwoWay 바인딩은 대상과 소스 중 하나가 변경될 때 대상과 소스를 모두 업데이트합니다. 또는 자동 소스 업데이트를 비활성화하고 원할 때만 소스를 업데이트할 수 있습니다.

자동 대상 업데이트가 발생하도록 하려면 다음 단원의 설명대로 소스 개체가 INotifyPropertyChanged 인터페이스를 구현해야 합니다.

소스 개체의 변경 내용을 대상으로 전파하려면 소스가 INotifyPropertyChanged 인터페이스를 구현해야 합니다. INotifyPropertyChangedPropertyChanged 이벤트는 바인딩 엔진이 대상 값을 업데이트할 수 있도록 소스가 변경되었음을 바인딩 엔진에 알립니다.

다음 예제에서 MyColors 클래스는 OneWay 바인딩에 대한 INotifyPropertyChanged 인터페이스를 구현합니다.


// Create a class that implements INotifyPropertyChanged.
public class MyColors : INotifyPropertyChanged
{
    private SolidColorBrush _Brush1;

    // Declare the PropertyChanged event.
    public event PropertyChangedEventHandler PropertyChanged;

    // Create the property that will be the source of the binding.
    public SolidColorBrush Brush1
    {
        get { return _Brush1; }
        set
        {
            _Brush1 = value;
            // Call NotifyPropertyChanged when the source property 
            // is updated.
            NotifyPropertyChanged("Brush1");
        }
    }


    // NotifyPropertyChanged will raise the PropertyChanged event, 
    // passing the source property that is being updated.
    public void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, 
                new PropertyChangedEventArgs(propertyName));
        }
    }
}


ItemsControl에 바인딩된 컬렉션에 대한 변경 알림을 가져오려면 INotifyPropertyChanged 외에도 INotifyCollectionChanged를 구현합니다. INotifyCollectionChanged를 구현하면 개체 추가 또는 제거와 같은 컬렉션 변경 내용이 대상으로 전파됩니다. 컬렉션에서 개체에 대한 속성 변경 알림을 가져오려면 개체에 INotifyPropertyChanged를 구현해야 합니다.

사용자 고유의 컬렉션을 구현하기 전에 INotifyCollectionChangedINotifyPropertyChanged의 기본 제공 구현을 포함하는 ObservableCollection<T> 클래스 사용을 고려하세요.

TwoWay 바인딩에서 대상을 변경하면 TextBoxText 속성에 바인딩하는 경우를 제외하고 자동으로 소스가 업데이트됩니다. 이 경우 TextBox가 포커스를 잃으면 업데이트가 발생합니다.

자동 소스 업데이트를 비활성화하고 원할 때 소스를 업데이트할 수 있습니다. 예를 들어 이와 같이 하기 위해 바인딩된 데이터 소스를 업데이트하기 전에 여러 컨트롤로부터의 사용자 입력이 유효한지 검사할 수 있습니다.

자동 소스 업데이트를 비활성화하려면 UpdateSourceTrigger 속성을 Explicit로 설정합니다. 이 설정은 상속된 데이터 컨텍스트를 사용하는 경우와 같이 동일한 Binding 개체를 사용하는 모든 바인딩에 영향을 줍니다. 그러나 각 바인딩에 대한 소스를 개별적으로 업데이트해야 합니다. 바인딩을 업데이트하려면 먼저 대상 요소의 FrameworkElement.GetBindingExpression 메서드를 호출하고 대상 DependencyProperty를 전달합니다. 그런 다음 반환 값을 사용하여 BindingExpression.UpdateSource 메서드를 호출할 수 있습니다. 다음 예제 코드에서는 이 프로세스를 보여 줍니다.


<TextBox x:Name="textBox1" Text="{Binding Test, Mode=TwoWay, UpdateSourceTrigger=Explicit}" />
<Button Content="Update" Click="Button_Click" />



public class TestData
{
    public String Test { get; set; }
}

TestData data;

public MainPage()
{
    InitializeComponent();
    data = new TestData { Test = "one" };
    textBox1.DataContext = data;
}

private void Button_Click(object sender, RoutedEventArgs e)
{
    BindingExpression expression = textBox1.GetBindingExpression(TextBox.TextProperty);
    MessageBox.Show("Before UpdateSource, Test = " + data.Test);
    expression.UpdateSource();
    MessageBox.Show("After UpdateSource, Test = " + data.Test);
}


바인딩 소스 개체는 해당 속성에 데이터가 들어 있는 단일 개체 또는 개체 컬렉션으로 처리될 수 있습니다. 예를 들어, 월별 신용 카드 대금 청구서와 같은 항목 목록을 표시하려고 할 수 있습니다. 이렇게 하려면 ItemsControl을 사용하고 DataTemplate을 사용하여 컬렉션의 항목을 각각 표시합니다.


<Grid.Resources>
  <DataTemplate x:Name="dataTemplate">
    <Grid>
      <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
      </Grid.ColumnDefinitions>

      <TextBlock Grid.Column="0" 
          Text="{Binding Month, Converter={StaticResource Converter1}}"/>
      <TextBlock Grid.Column="1" Text="{Binding Total}"/>    
    </Grid>
  </DataTemplate>
</Grid.Resources>

<ItemsControl x:Name="IC1" ItemsSource="{Binding}" 
  ItemTemplate="{StaticResource dataTemplate}"/>


IEnumerable을 구현하는 모든 컬렉션을 열거할 수 있습니다. 컬렉션이 변경될 때 대상에서 ItemsSource를 업데이트하도록 하려면 INotifyCollectionChanged를 구현하세요. 변경 알림에 대한 자세한 내용은 이 항목의 앞부분에 나오는 "변경 알림" 단원을 참조하세요.

다른 데이터 소스에 대한 정렬, 그룹화, 필터링 및 통화 지원을 제공하는 CollectionViewSource 클래스의 인스턴스에 바인딩할 수도 있습니다. CollectionViewSource를 사용하면 사용자 선택 변경과 동기화되는 여러 데이터 뷰를 표시할 수 있습니다.

CollectionViewSource를 사용하여 계층적으로 관련된 데이터에 여러 컨트롤을 바인딩할 수도 있습니다.

컨트롤을 바인딩할 수 있도록 개체에 제네릭 목록을 캡슐화하는 방법에 대한 자세한 내용은 List<T>Dictionary<TKey, TValue>에 대한 첫 번째 코드 예제를 참조하세요.

Windows Phone 은 대상에서 소스로의 업데이트에 대한 TwoWay 바인딩에서 간단한 데이터 유효성 검사를 지원합니다.

Windows Phone 에서는 바인딩의 Validation.Errors 연결 속성에 오류가 있을 때마다 유효성 검사 오류를 보고합니다. 다음과 같은 경우 오류가 이 컬렉션에 추가됩니다.

  • 바인딩 엔진의 형식 변환기에서 예외가 발생할 경우

  • 바인딩 개체의 set 접근자에서 예외가 발생할 경우

  • 데이터 개체나 멤버에 적용된 유효성 검사 특성에서 예외가 발생할 경우

  • 바인딩 개체가 IDataErrorInfo를 구현하고, 해당 Item 속성이 null 또는 Empty가 아닌 값을 반환할 경우

  • 바인딩 개체가 INotifyDataErrorInfo를 구현하고, 해당 GetErrors 메서드가 null이 아닌 값을 반환할 경우. GetErrors 반환 값은 비동기 유효성 검사 작업의 완료 결과로 변경될 수 있습니다.

Windows Phone 에서는 다음과 같은 경우 유효성 검사 오류에 대한 시각적 피드백을 제공합니다.

시각적 피드백은 오류가 포함된 컨트롤을 나타내고 근처에 오류 메시지를 표시합니다.

유효성 검사 오류가 발생했거나 해결되었다는 알림을 받으려면 바인딩 개체의 NotifyOnValidationError 속성을 true로 설정해야 합니다. 이렇게 하면 유효성 검사 오류가 Validation.Errors 컬렉션에 추가되거나 이 컬렉션에서 제거될 때 바인딩 엔진에서 BindingValidationError 이벤트를 발생합니다. 예를 들어 오류 이벤트를 처리하여 오류를 기록하거나 추가로 시각적 피드백을 제공할 수 있습니다.

BindingValidationError 이벤트를 처리하려면 대상 개체나 부모 개체에 이벤트 처리기를 만듭니다. BindingValidationError 이벤트는 라우트된 이벤트이므로 이벤트를 발생시키는 요소에서 이를 처리하지 않으면 처리될 때까지 위쪽으로 버블링됩니다. 라우트된 이벤트에 대한 자세한 내용은 Windows Phone의 텍스트를 참조하세요.

다음 예제에서는 사용자 지정 바인딩 유효성 검사를 제공하는 방법을 보여 줍니다.

바인딩은 XAML에서 만들어집니다.


<StackPanel BindingValidationError="StackPanel_BindingValidationError" >
    <StackPanel.Resources>
        <my:Bills x:Name="MyBills"/>
    </StackPanel.Resources>

    <TextBlock 
        TextWrapping="Wrap"
        Text="To generate a validation error, input a negative number or a non-number and then tap the button."
    />

    <TextBox x:Name="MyTextBox" Width="50" Margin="10">
        <TextBox.Text>
            <Binding Mode="TwoWay" Source="{StaticResource MyBills}" 
                 Path="Amount" NotifyOnValidationError="true" 
                 ValidatesOnExceptions="true"/>
        </TextBox.Text>
    </TextBox>
    <Button Content="Tap to Update"/>
</StackPanel>


값이 음수인 경우 소스 개체는 set 접근자에서 예외를 발생합니다.


public class Bills
{
    private double _Amount;
    public double Amount
    {
        get { return _Amount; }
        set
        {
            if (value < 0)
                throw new Exception("Amount must be greater than zero.");
            _Amount = value;
        }
    }

}


StackPanelBindingValidationError 이벤트의 처리기를 구현합니다.


private void StackPanel_BindingValidationError(object sender, 
    ValidationErrorEventArgs e)
{
    if (e.Action == ValidationErrorEventAction.Added)
    {
        MyTextBox.Background = new SolidColorBrush(Colors.Red);

    }
    else if (e.Action == ValidationErrorEventAction.Removed)
    {
        MyTextBox.Background = new SolidColorBrush(Colors.White);
    }
}


이 코드 예제에서는 숫자 대신 문자를 입력하여 형식 변환기에서 발생되는 오류를 가져옵니다. 소스 개체의 set 접근자에서 발생하는 오류를 가져오려면 음수를 입력합니다. 유효성 검사 오류를 확인하려면 양수를 입력합니다. TextBox가 포커스를 잃는 경우에만 TextBox 대상에서 소스로의 업데이트가 발생합니다. 포커스를 변경하는 버튼이 제공됩니다. 원하는 경우 버튼 클릭에 대한 응답으로 소스를 수동으로 업데이트할 수 있습니다("데이터 소스 업데이트" 섹션의 앞부분 참조).

데이터 저장 방식과 다른 형식으로 데이터를 표시해야 할 수도 있습니다. 다음은 몇 가지 예입니다.

  • 색을 RGBA 값으로 저장하지만 문자열 이름으로 표시

  • 숫자를 부동 소수점 값으로 저장하지만 통화 값으로 표시

  • 날짜를 DateTime으로 저장하지만 달력으로 표시

  • null 값으로 저장하지만 기본값으로 표시

StringFormat 속성을 설정하여 표시할 String 값의 형식을 지정할 수 있습니다.

TargetNullValue 속성을 설정하여 null 지원 값에 대해 친숙한 기본값을 표시할 수도 있습니다.

모든 바인딩에 변환기를 설정할 수도 있습니다. 각 시나리오에 대해 클래스를 만들고 IValueConverter 인터페이스를 구현하여 변환기를 사용자 지정합니다. 다음 예제에서는 IValueConverter를 구현하는 방법을 보여 줍니다.


// Custom class implements the IValueConverter interface.
public class DateToStringConverter : IValueConverter
{

    #region IValueConverter Members

    // Define the Convert method to change a DateTime object to 
    // a month string.
    public object Convert(object value, Type targetType, 
        object parameter, 
System.Globalization.CultureInfo culture)
    {
        // value is the data from the source object.
        DateTime thisdate = (DateTime)value;
        int monthnum = thisdate.Month;
        string month;
        switch (monthnum)
        {
            case 1:
                month = "January";
                break;
            case 2:
                month = "February";
                break;
            default:
                month = "Month not found";
                break;
        }
        // Return the value to pass to the target.
        return month;

    }

    // ConvertBack is not implemented for a OneWay binding.
    public object ConvertBack(object value, Type targetType, 
        object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    #endregion
}


바인딩에 Converter 매개 변수가 정의되었을 경우 바인딩 엔진은 ConvertConvertBack 메서드를 호출합니다. 소스에서 데이터가 전달되면 바인딩 엔진은 Convert를 호출하여 반환된 데이터를 대상으로 전달합니다. 대상에서 데이터가 전달되면 바인딩 엔진은 ConvertBack을 호출하여 반환된 데이터를 소스로 전달합니다. 다음 예제에서는 Converter 매개 변수를 설정하는 방법을 보여 줍니다.


<phone:PhoneApplicationPage.Resources>
  <local:DateToStringConverter x:Key="Converter1"/>
</phone:PhoneApplicationPage.Resources>


...


<TextBlock Grid.Column="0" 
    Text="{Binding Month, Converter={StaticResource Converter1}}"/>


변환기에는 선택적 매개 변수도 있습니다. ConverterCulture 매개 변수를 사용하면 변환에 사용되는 문화권을 지정할 수 있고 ConverterParameter 매개 변수를 사용하면 변환 논리에 대한 매개 변수를 전달할 수 있습니다. 이러한 매개 변수를 사용하는 예제는 IValueConverter를 참조하세요.

변환에 오류가 있는 경우 예외를 발생하지 마세요. 대신 데이터 전송을 중지하는 DependencyProperty.UnsetValue를 반환합니다.

바인딩 소스를 확인할 수 없을 때마다 나타나는 기본값을 표시하려면 FallbackValue 속성을 설정합니다. 이렇게 하면 변환 및 형식 지정 오류를 처리하는 데 유용합니다. 또한 바인딩된 컬렉션의 일부 개체에 없을 수도 있는 소스 속성에 바인딩할 때에도 유용합니다.

표시:
© 2014 Microsoft