이벤트 기반 UI와 데이터 바인딩된 UI 비교
- 6분
이벤트 기반 UI(사용자 인터페이스)는 컨트롤이 노출하는 이벤트를 중심으로 설계되었습니다. 이러한 이벤트는 이벤트가 트리거될 때 호출되는 이벤트 처리기 코드와 연결할 수 있습니다. 예를 들어 클릭하면 장기 실행 작업을 수행하는 단추가 있다고 가정해 보겠습니다. Clicked 이벤트에 할당된 이벤트 처리기는 작업을 시작한 다음 단추의 IsEnabled 속성을 false로 설정하여 작업이 실행되는 동안 단추를 다시 클릭하지 못하도록 할 수 있습니다.
데이터 바인딩된 UI는 데이터 바인딩을 사용하여 데이터를 표시하고 데이터와 상호 작용합니다. 컨트롤의 속성은 데이터 개체의 속성에 바인딩되며, 해당 바인딩은 속성의 변경을 검색할 수 있습니다. 이전 예를 들어, 장기 실행 작업을 수행하는 단추를 생각해 보겠습니다. 코드 숨김에서 단추를 사용하지 않도록 설정하는 대신, IsEnabled 속성이 데이터 개체의 IsBusy 속성에 바인딩됩니다. 데이터 개체가 "사용 중"이 될 때마다 단추의 사용 상태가 자동으로 일치하도록 변경됩니다.
이벤트와 코드-비하인드 사용의 장단점
코드 숨김과 함께 컨트롤의 이벤트 처리기를 사용하면 UI에 대한 앱 논리를 빠르고 편리하게 설계할 수 있습니다. 코드를 사용해 서비스를 호출하여 데이터를 가져오고, 해당 데이터에 대한 작업을 수행하고, 페이지의 컨트롤과 상호 작용합니다. 해당 코드는 UI와 데이터의 동기화를 유지하는 데 사용됩니다.
날씨 서비스 앱의 예를 들어 보겠습니다. 다음 XAML 조각에는 사용자가 최신 데이터를 가져오고 습도로 UI를 업데이트하기 위해 선택하는 간단한 UI 단추가 포함되어 있습니다.
<VerticalStackLayout Margin="10">
<HorizontalStackLayout Spacing="20">
<Label Text="Postal Code:" VerticalOptions="Center" />
<Entry x:Name="PostalCode" WidthRequest="100" />
<Button x:Name="RefreshWeatherButton" Text="Refresh" WidthRequest="200" Clicked="RefreshWeatherButton_Clicked" />
</HorizontalStackLayout>
<Label x:Name="Humidity" Text="Humidity: ?" />
</VerticalStackLayout>
이 예에는 세 개의 명명된 컨트롤이 있습니다.
Entry컨트롤의 이름은 PostalCode입니다.Button컨트롤의 이름이 RefreshWeatherButton입니다.Label컨트롤의 이름이 Humidity입니다.
RefreshWeatherButton에는 Clicked 이벤트에 대해 선언된 이벤트 처리기가 있습니다. 단추를 클릭하면 이벤트 처리기는 입력 컨트롤에 입력한 PostalCode 데이터를 사용하여 최신 일기 예보에 대한 날씨 서비스를 쿼리하고 레이블의 텍스트를 현재 습도로 설정합니다 Humidity .
private void RefreshWeatherButton_Clicked(object sender, EventArgs e)
{
WeatherService.Location = PostalCode.Text;
WeatherService.Refresh();
Humidity.Text = $"Humidity: {WeatherService.Humidity}";
}
이 이벤트 처리기에서는 세 개의 컨트롤이 서로 및 데이터와 코드 비하인드를 통해 밀접하게 결합되어 있습니다.
이런 디자인은 작은 UI에는 적합하지만, UI가 복잡해지면 밀접하게 결합된 코드 숨김을 유지하는 것이 번거로워질 수 있습니다. 컨트롤을 삭제하거나 변경하는 경우 해당 UI 컨트롤을 사용하는 모든 코드(이벤트 처리기 포함)를 정리해야 합니다. UI를 다시 디자인하려는 경우 리팩터링할 코드도 많이 있습니다. 그리고 백업 데이터 구조가 변경되면 동기화를 유지하기 위해 각 UI의 코드를 자세히 살펴봐야 합니다.
데이터 바인딩 도움
XAML 또는 코드에서 데이터 바인딩을 구현할 수 있지만 XAML에서 훨씬 더 일반적입니다. 여기서 코드 숨김 파일 크기를 줄이는 데 도움이 됩니다. 이벤트 처리기의 절차 코드를 선언적 코드 또는 태그로 바꾸면 앱이 간소화되고 명확해집니다. 바인딩에는 코드 숨김이 필요하지 않으므로 데이터를 표시하려는 방식에 맞게 UI를 쉽게 만들기, 변경 또는 재설계할 수 있습니다.
이전 섹션과 동일한 예를 살펴보겠지만, 데이터 바인딩을 사용하도록 업데이트해 보겠습니다.
<VerticalStackLayout Margin="10">
<HorizontalStackLayout Spacing="20">
<Label Text="Postal Code:" VerticalOptions="Center" />
<Entry Text="{Binding Location, Mode=OneWayToSource}" WidthRequest="100" />
<Button Text="Refresh" Command="{Binding RefreshWeather}" WidthRequest="200" />
</HorizontalStackLayout>
<Label Text="{Binding Humidity}" />
</VerticalStackLayout>
데이터 바인딩된 속성을 파악할 수 있으며, 속성 값에 대해 XAML 확장 구문 {Binding ...}을 사용합니다. 세부 사항에 대해서는 아직 걱정하지 마세요. 이 모듈의 뒷부분에서 설명합니다.
동일한 세 개의 컨트롤이 XAML에서 선언되지만 이름이 필요하지 않으므로 이름이 지정되지 않습니다.
Entrycontrol: 이 컨트롤의Text속성은 명명Location된 속성에 바인딩됩니다.Buttoncontrol: 단추의Command속성은 명명RefreshWeather된 속성에 바인딩됩니다.Command는 단추를 눌렀을 때 코드를 호출하는 단추의 속성입니다. 이는 데이터 바인딩에 사용되는Clicked이벤트의 대안입니다.Labelcontrol: 이Text속성은 명명Humidity된 속성에 바인딩됩니다.
이 간단한 UI에서는 모든 코드 비하인드가 제거되었습니다. 코드 숨김을 모두 제거하는 것이 데이터 바인딩의 목적은 아닙니다, 가능하더라도. 코드 숨김은 여전히 적용되어 있습니다. 얼마나 많은 데이터 바인딩을 구현할지는 사용자에게 달려 있습니다.
이제 UI가 데이터 개체에 느슨하게 결합됩니다. 왜 단단히 결합된 것이 아니라 느슨하게 결합된 것일까요? 바인딩이 평가되는 방식 때문입니다. 각 컨트롤에는 BindingContext 속성이 있습니다. 컨텍스트가 설정되지 않은 경우 부모 컨트롤의 컨텍스트가 사용되는 식으로 XAML 루트가 평가될 때까지 계속됩니다. 바인딩이 평가될 때 컨텍스트의 개체 인스턴스가 필요한 속성(예: 레이블 컨트롤의 Text 바인딩이 컨텍스트의 Humidity 속성에 바인딩되는 것)에 대해 확인됩니다. 컨텍스트에 Humidity가 없으면 아무 일도 일어나지 않습니다.
UI가 느슨하게 결합되어 있으므로 코드 분리에 대한 걱정 없이 UI를 다시 디자인할 수 있습니다. 하지만 기능을 손상시킬 수도 있습니다. 예를 들어, 단추를 삭제해도 앱은 계속 컴파일되고 실행되지만, 날씨를 새로 고칠 방법은 없습니다. 반면에 Entry 및 Button 컨트롤을 단일 SearchBar 컨트롤로 바꿀 수 있습니다. 이 컨트롤을 사용하면 텍스트를 입력하고 명령을 실행할 수 있습니다.
<SearchBar Text="{Binding Location, Mode=OneWayToSource}" SearchCommand="{Binding RefreshWeather}" />
보시다시피 UI 디자인에서 데이터 바인딩을 사용하면 큰 작업 없이 UI를 진화시키고 변경하는 데 도움이 됩니다. UI가 데이터와 자동으로 동기화되고 앱 논리가 UI와 분리됩니다.