다음을 통해 공유


4부. 데이터 바인딩 기본 사항

데이터 바인딩을 사용하면 두 개체의 속성을 연결하여 한 개체의 변경으로 인해 다른 개체가 변경되도록 할 수 있습니다. 이 도구는 매우 유용한 도구이며, 데이터 바인딩을 코드에서 완전히 정의할 수 있지만 XAML은 바로 가기와 편의를 제공합니다. 따라서 바인딩에서 Xamarin.Forms 가장 중요한 태그 확장 중 하나가 됩니다.

데이터 바인딩

데이터 바인딩은 원본대상이라는 두 개체의 속성을 연결합니다. 코드에서는 두 단계가 필요합니다 BindingContext . 대상 개체의 속성을 원본 개체로 설정해야 하며 SetBinding 대상 개체에서 메서드(클래스와 함께 Binding 자주 사용됨)를 호출하여 해당 개체의 속성을 원본 개체의 속성에 바인딩해야 합니다.

대상 속성은 바인딩 가능한 속성이어야 합니다. 즉, 대상 개체에서 파생 BindableObject되어야 합니다. 온라인 Xamarin.Forms 설명서는 바인딩 가능한 속성인 속성을 나타냅니다. 이러한 Text 속성 Label 은 바인딩 가능한 속성TextProperty과 연결됩니다.

태그에서 태그 확장이 호출과 Binding 클래스를 대신 SetBinding 한다는 점을 Binding 제외하고 코드에 필요한 동일한 두 단계를 수행해야 합니다.

그러나 XAML에서 데이터 바인딩을 정의하는 경우 대상 개체를 설정하는 방법에는 여러 가지가 BindingContext 있습니다. 경우에 따라 코드 숨김 파일에서 설정되고, 경우에 따라 확장 프로그램 StaticResource 또는 태그 확장을 사용하며 x:Static , 때로는 속성 요소 태그의 BindingContext 콘텐츠로 설정되기도 합니다.

바인딩은 프로그램의 시각적 개체를 기본 데이터 모델과 연결하는 데 가장 자주 사용되며, 일반적으로 5부에서 설명한 대로 MVVM(Model-View-ViewModel) 애플리케이션 아키텍처를 실현합니다. 데이터 바인딩에서 MVVM으로, 그러나 다른 시나리오는 가능합니다.

보기-보기 바인딩

데이터 바인딩을 정의하여 동일한 페이지에서 두 뷰의 속성을 연결할 수 있습니다. 이 경우 태그 확장을 사용하여 대상 개체를 x:Reference 설정합니다BindingContext.

다음은 값으로 회전 Slider 되고 다른 하나는 값을 표시하는 Slider 두 개의 Label 뷰를 포함하는 Slider XAML 파일입니다.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.SliderBindingsPage"
             Title="Slider Bindings Page">

    <StackLayout>
        <Label Text="ROTATION"
               BindingContext="{x:Reference Name=slider}"
               Rotation="{Binding Path=Value}"
               FontAttributes="Bold"
               FontSize="Large"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand" />

        <Slider x:Name="slider"
                Maximum="360"
                VerticalOptions="CenterAndExpand" />

        <Label BindingContext="{x:Reference slider}"
               Text="{Binding Value, StringFormat='The angle is {0:F0} degrees'}"
               FontAttributes="Bold"
               FontSize="Large"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand" />
    </StackLayout>
</ContentPage>

태그 Slider 확장을 사용하여 x:ReferenceLabel 뷰에서 참조하는 특성을 포함합니다x:Name.

바인딩 확장은 x:Reference 이 경우 slider참조된 요소의 이름으로 설정하도록 명명 Name 된 속성을 정의합니다. 그러나 ReferenceExtension 태그 확장을 정의하는 x:Reference 클래스는 명시적으로 필요하지 않음을 의미하는 특성Name도 정의 ContentProperty 합니다. 다양성을 위해 첫 번째는 x:Reference "Name="를 포함하지만 두 번째는 다음을 수행하지 않습니다.

BindingContext="{x:Reference Name=slider}"
…
BindingContext="{x:Reference slider}"

태그 확장 자체에는 Binding 클래스와 Binding 같은 여러 속성이 BindingBase 있을 수 있습니다. for BindingContentProperty Path태그 확장의 첫 번째 항목 Binding 인 경우 태그 확장의 "Path=" 부분을 생략할 수 있습니다. 첫 번째 예제에는 "Path="가 있지만 두 번째 예제에서는 생략합니다.

Rotation="{Binding Path=Value}"
…
Text="{Binding Value, StringFormat='The angle is {0:F0} degrees'}"

속성은 모두 한 줄에 있거나 여러 줄로 구분될 수 있습니다.

Text="{Binding Value,
               StringFormat='The angle is {0:F0} degrees'}"

편리한 모든 작업을 수행합니다.

StringFormat 두 번째 Binding 태그 확장의 속성을 확인합니다. 에서 Xamarin.Forms바인딩은 암시적 형식 변환을 수행하지 않으며 문자열이 아닌 개체를 문자열로 표시해야 하는 경우 형식 변환기를 제공하거나 사용해야 StringFormat합니다. 백그라운드에서 정적 String.Format 메서드는 구현 StringFormat하는 데 사용됩니다. .NET 서식 지정 사양에는 태그 확장을 구분하는 데 사용되는 중괄호가 포함되기 때문에 잠재적으로 문제가 될 수 있습니다. 이로 인해 XAML 파서가 혼동될 위험이 있습니다. 이를 방지하려면 전체 서식 문자열을 작은따옴표로 묶습니다.

Text="{Binding Value, StringFormat='The angle is {0:F0} degrees'}"

실행 중인 프로그램은 다음과 같습니다.

보기-보기 바인딩

바인딩 모드

단일 보기에는 여러 속성에 대한 데이터 바인딩이 있을 수 있습니다. 그러나 각 뷰에는 하나의 BindingContext데이터 바인딩만 있을 수 있으므로 해당 뷰의 여러 데이터 바인딩은 동일한 개체의 모든 참조 속성을 참조해야 합니다.

이 문제 및 기타 문제에 대한 해결 방법은 열거형의 멤버로 설정된 속성과 BindingMode 관련이 Mode 있습니다.

  • Default
  • OneWay — 값이 원본에서 대상으로 전송됩니다.
  • OneWayToSource — 값이 대상에서 원본으로 전송됩니다.
  • TwoWay — 값은 원본과 대상 간에 두 가지 방법으로 전송됩니다.
  • OneTime — 데이터가 원본에서 대상으로 바뀌지만 변경되는 BindingContext 경우에만

다음 프로그램은 바인딩 모드와 TwoWay 바인딩 모드를 OneWayToSource 일반적으로 사용하는 방법을 보여 줍니다. 4개의 Slider 뷰는 .의 , RotateRotateXRotateY 속성을 제어Scale하기 위한 것입니다Label. 처음에는 각각에 의해 설정되기 때문에 이러한 네 가지 속성이 Label 데이터 바인딩 대상이어야 하는 Slider것처럼 보입니다. 그러나 해당 Label 개체는 BindingContext 하나의 개체일 수 있으며 4개의 서로 다른 슬라이더가 있습니다.

이러한 이유로 모든 바인딩은 겉보기에 뒤로 BindingContext 설정됩니다. 네 개의 슬라이더 각각이 슬라이더로 Label설정되고 바인딩은 슬라이더의 속성에 Value 설정됩니다. 및 TwoWay 모드를 OneWayToSource 사용하여 이러한 Value 속성은 다음의 , RotateRotateY RotateX속성인 소스 Scale속성을 Label설정할 수 있습니다.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.SliderTransformsPage"
             Padding="5"
             Title="Slider Transforms Page">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>

        <!-- Scaled and rotated Label -->
        <Label x:Name="label"
               Text="TEXT"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand" />

        <!-- Slider and identifying Label for Scale -->
        <Slider x:Name="scaleSlider"
                BindingContext="{x:Reference label}"
                Grid.Row="1" Grid.Column="0"
                Maximum="10"
                Value="{Binding Scale, Mode=TwoWay}" />

        <Label BindingContext="{x:Reference scaleSlider}"
               Text="{Binding Value, StringFormat='Scale = {0:F1}'}"
               Grid.Row="1" Grid.Column="1"
               VerticalTextAlignment="Center" />

        <!-- Slider and identifying Label for Rotation -->
        <Slider x:Name="rotationSlider"
                BindingContext="{x:Reference label}"
                Grid.Row="2" Grid.Column="0"
                Maximum="360"
                Value="{Binding Rotation, Mode=OneWayToSource}" />

        <Label BindingContext="{x:Reference rotationSlider}"
               Text="{Binding Value, StringFormat='Rotation = {0:F0}'}"
               Grid.Row="2" Grid.Column="1"
               VerticalTextAlignment="Center" />

        <!-- Slider and identifying Label for RotationX -->
        <Slider x:Name="rotationXSlider"
                BindingContext="{x:Reference label}"
                Grid.Row="3" Grid.Column="0"
                Maximum="360"
                Value="{Binding RotationX, Mode=OneWayToSource}" />

        <Label BindingContext="{x:Reference rotationXSlider}"
               Text="{Binding Value, StringFormat='RotationX = {0:F0}'}"
               Grid.Row="3" Grid.Column="1"
               VerticalTextAlignment="Center" />

        <!-- Slider and identifying Label for RotationY -->
        <Slider x:Name="rotationYSlider"
                BindingContext="{x:Reference label}"
                Grid.Row="4" Grid.Column="0"
                Maximum="360"
                Value="{Binding RotationY, Mode=OneWayToSource}" />

        <Label BindingContext="{x:Reference rotationYSlider}"
               Text="{Binding Value, StringFormat='RotationY = {0:F0}'}"
               Grid.Row="4" Grid.Column="1"
               VerticalTextAlignment="Center" />
    </Grid>
</ContentPage>

Slider 개의 뷰에 대한 바인딩은 OneWayToSource값이 명명label된 해당 속성의 BindingContextLabel 변경이 발생한다는 Slider 것을 의미합니다. 이러한 세 Slider 가지 보기는 . RotateXRotateY LabelRotate

그러나 속성에 대한 바인딩은 Scale .입니다 TwoWay. 이는 속성의 Scale 기본값이 1이고 바인딩 SliderTwoWay 사용하면 초기 값이 0이 아닌 1로 설정되기 때문입니다. 해당 바인딩인 OneWayToSource경우 속성은 Scale 처음에 기본값에서 Slider 0으로 설정됩니다. 표시되지 Label 않으므로 사용자에게 약간의 혼란이 발생할 수 있습니다.

뒤로 바인딩

참고 항목

클래스에는 VisualElement ScaleX 각각 x축과 ScaleY y축의 VisualElement 배율을 조정하는 속성과 속성도 있습니다.

바인딩 및 컬렉션

템플릿 ListView기반보다 XAML 및 데이터 바인딩의 기능을 보여 줍니다.

ListViewItemsSource 형식 IEnumerable의 속성을 정의하고 해당 컬렉션의 항목을 표시합니다. 이러한 항목은 모든 형식의 개체일 수 있습니다. 기본적으로 ListView 각 항목의 ToString 메서드를 사용하여 해당 항목을 표시합니다. 경우에 따라 이는 원하는 것일 뿐이지만 대부분의 경우 ToString 개체의 정규화된 클래스 이름만 반환합니다.

그러나 파생 클래스를 ListView 포함하는 템플릿을 사용하여 컬렉션의 항목을 원하는 방식으로 표시할 수 있습니다Cell. 템플릿은 모든 항목에 ListView대해 복제되며 템플릿에 설정된 데이터 바인딩은 개별 클론으로 전송됩니다.

클래스를 사용하여 ViewCell 이러한 항목에 대한 사용자 지정 셀을 만드는 경우가 많습니다. 이 프로세스는 코드에서 다소 지저분하지만 XAML에서는 매우 간단합니다.

XamlSamples 프로젝트에 포함된 클래스는 다음과 같습니다 NamedColor. 각 NamedColor 개체에는 Name 형식의 속성과 FriendlyName 형식stringColor속성이 Color 있습니다. 또한 NamedColor 클래스에 정의된 색에 해당하는 형식 Color 의 정적 읽기 전용 필드가 141개 있습니다 Xamarin.FormsColor . 정적 생성자는 이러한 정적 필드에 해당하는 개체를 포함하는 NamedColor 컬렉션을 만들고 IEnumerable<NamedColor> 해당 공용 정적 All 속성에 할당합니다.

태그 확장을 사용하면 정적 NamedColor.All 속성을 ItemsSource a ListView 로 쉽게 설정할 수 x:Static 있습니다.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:XamlSamples;assembly=XamlSamples"
             x:Class="XamlSamples.ListViewDemoPage"
             Title="ListView Demo Page">

    <ListView ItemsSource="{x:Static local:NamedColor.All}" />

</ContentPage>

결과 디스플레이는 항목이 진정한 형식 XamlSamples.NamedColor임을 설정합니다.

컬렉션에 바인딩

많은 정보는 아니지만 ListView 스크롤 가능하고 선택할 수 있습니다.

항목에 대한 템플릿을 정의하려면 속성을 속성 요소로 분리 ItemTemplate 한 다음 속성 요소로 설정한 다음 참조하는 템플릿으로 ViewCell설정DataTemplate해야 합니다. 속성 ViewCellView 대해 하나 이상의 보기 레이아웃을 정의하여 각 항목을 표시할 수 있습니다. 다음은 간단한 예제입니다.

<ListView ItemsSource="{x:Static local:NamedColor.All}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <ViewCell.View>
                    <Label Text="{Binding FriendlyName}" />
                </ViewCell.View>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

참고 항목

셀과 셀의 자식에 대한 바인딩 소스는 ListView.ItemsSource 컬렉션입니다.

Label 요소가 .의 View 속성으로 설정됩니다ViewCell. 속성이 ViewCell.View .의 ViewCell콘텐츠 속성이므로 태그가 필요하지 View 않습니다. 이 태그는 각 NamedColor 개체의 FriendlyName 속성을 표시합니다.

DataTemplate을 사용하여 컬렉션에 바인딩

훨씬 나은. 이제 필요한 것은 항목 템플릿을 더 많은 정보와 실제 색으로 가문비나무로 만드는 것입니다. 이 템플릿을 지원하기 위해 페이지의 리소스 사전에 일부 값과 개체가 정의되었습니다.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:XamlSamples"
             x:Class="XamlSamples.ListViewDemoPage"
             Title="ListView Demo Page">

    <ContentPage.Resources>
        <ResourceDictionary>
            <OnPlatform x:Key="boxSize"
                        x:TypeArguments="x:Double">
                <On Platform="iOS, Android, UWP" Value="50" />
            </OnPlatform>

            <OnPlatform x:Key="rowHeight"
                        x:TypeArguments="x:Int32">
                <On Platform="iOS, Android, UWP" Value="60" />
            </OnPlatform>

            <local:DoubleToIntConverter x:Key="intConverter" />

        </ResourceDictionary>
    </ContentPage.Resources>

    <ListView ItemsSource="{x:Static local:NamedColor.All}"
              RowHeight="{StaticResource rowHeight}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout Padding="5, 5, 0, 5"
                                 Orientation="Horizontal"
                                 Spacing="15">

                        <BoxView WidthRequest="{StaticResource boxSize}"
                                 HeightRequest="{StaticResource boxSize}"
                                 Color="{Binding Color}" />

                        <StackLayout Padding="5, 0, 0, 0"
                                     VerticalOptions="Center">

                            <Label Text="{Binding FriendlyName}"
                                   FontAttributes="Bold"
                                   FontSize="Medium" />

                            <StackLayout Orientation="Horizontal"
                                         Spacing="0">
                                <Label Text="{Binding Color.R,
                                       Converter={StaticResource intConverter},
                                       ConverterParameter=255,
                                       StringFormat='R={0:X2}'}" />

                                <Label Text="{Binding Color.G,
                                       Converter={StaticResource intConverter},
                                       ConverterParameter=255,
                                       StringFormat=', G={0:X2}'}" />

                                <Label Text="{Binding Color.B,
                                       Converter={StaticResource intConverter},
                                       ConverterParameter=255,
                                       StringFormat=', B={0:X2}'}" />
                            </StackLayout>
                        </StackLayout>
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</ContentPage>

행의 OnPlatform 크기와 높이 ListViewBoxView 정의하는 데 사용합니다. 모든 플랫폼의 값은 동일하지만 표시를 미세 조정하기 위해 다른 값에 맞게 태그를 쉽게 조정할 수 있습니다.

바인딩 값 변환기

이전 ListView 데모 XAML 파일은 구조체의Color Xamarin.Forms개별 RG및 속성을 표시합니다B. 이러한 속성은 형식 double 이며 범위는 0에서 1까지입니다. 16진수 값을 표시하려는 경우 단순히 "X2" 서식 지정 사양과 함께 사용할 StringFormat 수 없습니다. 정수에 대해서만 작동하며, 값은 double 255를 곱해야 합니다.

이 작은 문제는 바인딩 변환기라고도 하는 값 변환기를 사용하여 해결되었습니다. 인터페이스를 구현 IValueConverter 하는 클래스입니다. 즉, 두 개의 메서드가 명명 Convert 되고 ConvertBack. Convert 이 메서드는 값이 원본에서 대상으로 ConvertBack 전송될 때 호출됩니다. 대상에서 원본 OneWayToSource TwoWay 또는 바인딩으로의 전송을 위해 메서드가 호출됩니다.

using System;
using System.Globalization;
using Xamarin.Forms;

namespace XamlSamples
{
    class DoubleToIntConverter : IValueConverter
    {
        public object Convert(object value, Type targetType,
                              object parameter, CultureInfo culture)
        {
            double multiplier;

            if (!Double.TryParse(parameter as string, out multiplier))
                multiplier = 1;

            return (int)Math.Round(multiplier * (double)value);
        }

        public object ConvertBack(object value, Type targetType,
                                  object parameter, CultureInfo culture)
        {
            double divider;

            if (!Double.TryParse(parameter as string, out divider))
                divider = 1;

            return ((double)(int)value) / divider;
        }
    }
}

바인딩은 ConvertBack 원본에서 대상으로 가는 한 가지 방법일 뿐이므로 이 프로그램에서는 메서드가 역할을 하지 않습니다.

바인딩은 속성을 사용하여 바인딩 변환기를 참조합니다 Converter . 바인딩 변환기는 속성으로 지정된 매개 변수를 수락할 ConverterParameter 수도 있습니다. 다양한 기능을 위해 승수를 지정하는 방법입니다. 바인딩 변환기는 변환기 매개 변수에서 유효한 double 값을 확인합니다.

변환기는 리소스 사전에서 인스턴스화되므로 여러 바인딩 간에 공유할 수 있습니다.

<local:DoubleToIntConverter x:Key="intConverter" />

세 개의 데이터 바인딩은 이 단일 인스턴스를 참조합니다. 태그 확장에는 Binding 포함된 StaticResource 태그 확장이 포함되어 있습니다.

<Label Text="{Binding Color.R,
                      Converter={StaticResource intConverter},
                      ConverterParameter=255,
                      StringFormat='R={0:X2}'}" />

결과는 다음과 같습니다.

DataTemplate 및 변환기를 사용하여 컬렉션에 바인딩

기본 ListView 데이터에서 동적으로 발생할 수 있지만 특정 단계를 수행하는 경우에만 변경 내용을 처리하는 데 매우 정교합니다. 런타임 중에 변경 내용 속성에 ItemsSource 할당된 항목 컬렉션 ListView ( 즉, 컬렉션에 항목을 추가하거나 컬렉션에서 제거할 수 있는 경우)이면 이러한 항목에 대한 클래스를 ObservableCollection 사용합니다. ObservableCollection 는 인터페이스를 INotifyCollectionChanged 구현하고 ListView 이벤트에 대한 처리기를 설치합니다 CollectionChanged .

런타임 중에 항목 자체의 속성이 변경되는 경우 컬렉션의 항목은 인터페이스를 INotifyPropertyChanged 구현하고 이벤트를 사용하여 속성 값의 변경 내용을 신호로 표시 PropertyChanged 해야 합니다. 이 내용은 이 시리즈의 다음 부분인 5부에서 설명합니다. 데이터 바인딩에서 MVVM으로.

요약

데이터 바인딩은 페이지 내의 두 개체 간 또는 시각적 개체와 기본 데이터 간에 속성을 연결하는 강력한 메커니즘을 제공합니다. 그러나 애플리케이션이 데이터 원본 작업을 시작하면 인기 있는 애플리케이션 아키텍처 패턴이 유용한 패러다임으로 등장하기 시작합니다. 이 내용은 5부에서 다룹니다. 데이터 바인딩에서 MVVM으로.