본문 바로가기

Develop/MAUI 가이드

[Xamarin] MvvmCross 데이터 바인딩

반응형

MvvmCross
MvvmCross

MvvmCross 데이터 바인딩

데이터 바인딩은 MVVM 패턴에서 제일 핵심적인 기능입니다. 데이터 바인딩을 통해 View와 ViewModel 이 서로의 참조 변수를 가지지 않는 형태로 느슨한 결합을 유지할 수 있습니다. MVVM 패턴을 의도했지만 데이터 바인딩을 사용하지 않는다면 MVVM 패턴을 활용하지 못하는 겁니다. MvvmCross에서 데이터 바인딩을 구현하는 순서는 아래와 같습니다.

  1. ViewModel에 속성이 변경될 때마다 이벤트를 발생시키도록 구현한다.
  2. View에 ViewModel을 연결한다.
  3. View 속성에 ViewModel 속성을 Binding 한다.

1. ViewModel에 속성이 변경될 때마다 이벤트를 발생시키도록 구현한다.

데이터 바인딩의 핵심은 ViewModel이 INotifyPropertyChanged 인터페이스로 Event를 통해 View에게 데이터가 변화하였음을 알리는 겁니다. MvvmCross 에선 ViewModel에 MvvmCross.ViewModels.MvxViewModel 클래스를 상속받아, SetProperty 함수나 RaisePropertyChanged 함수로 데이터가 변화하였음을 알립니다.

    // MvxViewModel을 상속받는다.
    public class BaseViewModel : MvvmCross.ViewModels.MvxViewModel
    {
        // public 속성을 구현한다.
        private SomeModel _someModel;
        public string Name
        {
            get => _someModel.Name;
            /*
            SetProperty 함수는 내부적으로 값이 변화했는지 확인한 후 값을 변경하고 이벤트를 발생시킨다.
            */
            set => SetProperty(ref _someModel.Name, value);
        }

        public BaseViewModel()
        {

        }
    }

깔끔한 코드를 위해 View 에 ViewModel을 바인딩할 때 인터페이스로 받을 수 있도록 IBaseViewModel도 구현합니다.

    public interface IBaseViewModel : IMvxViewModel
    {
        string Name { get; }
    }

2. View에 ViewModel을 연결한다.

View에 ViewModel을 연결하는 방식은 3가지가 있습니다.

  • Xamarin 방식
  • MvvmCross 방식
  • behind 코드 방식

3가지 방식 이전에 공통적으로 구현해야 하는 사항은 아래와 같습니다.

먼저, BaseView는 MvxContentView를 상속받습니다.

    // 상속받을 때 ViewModel의 인터페이스를 지정한다.
    public partial class BaseView : MvxContentView<IBaseViewModel>
    {
        public BaseView()
        {
            InitializeComponent();
        }
    }

다음, BaseView.xaml 파일을 수정합니다.

<?xml version="1.0" encoding="UTF-8"?>
<?xaml-comp compile="true" ?>
<mvxforms:MvxContentView
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:Solution.Project"
    xmlns:mvxbind="clr-namespace:MvvmCross.Forms.Bindings;assembly=MvvmCross.Forms"
    xmlns:mvxforms="clr-namespace:MvvmCross.Forms.Views;assembly=MvvmCross.Forms"
    x:TypeArguments="local:IBaseViewModel"
    x:Class="Solution.Project.BaseView">
    <ContentView.Content>
            <Label x:Name="Label"
                   Text="Hello, World!" />
    </ContentView.Content>
</mvxforms:MvxContentView>

x:TypeArguments="local:IBaseViewModel" 를 지정하지 않으면 오류가 발생하니 주의바랍니다.

Xamarin 방식

<Label x:Name="Label"
       Text="{Binding Text}" />

MvvmCross 방식

<Label x:Name="Label"
       Text="Hello, World!"
       mvxbind:Bi.nd="Text Name"/>

프로젝트를 진행할 때 이상하게도 "mvxbind:Bi.nd" 가 정상적으로 동작하지 않을 때가 있었습니다. 그때는 behind 코드 방식 으로 데이터 바인딩을 구현하길 추천드립니다.

behind 코드 방식

    public partial class BaseView : MvxContentView<IBaseViewModel>
    {
        public BaseView()
        {
            InitializeComponent();
        }

        // ViewModel이 설정될 때 값을 바인딩합니다.
        protected override void OnViewModelSet()
        {
            base.OnViewModelSet();
            using (var set = this.CreateBindingSet<IBaseViewModel>())
            {
                set.Bind(Label)
                    .For(view => view.Text)
                    .To(viewmodel => viewmodel.Name);
            }
        }
    }
반응형