티스토리 뷰

반응형

사용자 정의 Confirm 박스를 만드는 방법에 대해 알아보자

 

앱을 개발하다 보면, Confirm을 해야 하는 경우가 발생하는데, 현재는 개발자가 만들어서 사용하는 방법 말고는 존재하지 않는다. ConfirmBox를 만들때 중요한 것은 사용자가 비동기 메소드를 만들고, 실행해서, 결과를 반환해야 한다는 것인데, 이 것을 만들기 위해서는 IAsyncInfo에 대한 내용을 알 필요가 있다.

 

1. IAsyncInfo Interface

참고 링크

http://msdn.microsoft.com/ko-kr/library/windows/apps/windows.foundation.iasyncinfo

 

Async 메소드의 결과를 처리하기 위해서는 기본적으로 IAsyncInfo 인터페이스를 반환해야한다. 이 인터페이스는 4개의 자식 인터페이스를 가진다.

 

 

* IAsyncAction 인터페이스

리턴 값이 없고, 비동기 Action이 완료되면 종료 한다.


* IAsyncActionWithProgress<TProgress> 인터페이스

리턴 값은 없는데, 진행 상황을 표시할 수 있는 프로그레스를 지원한다.


* IAsyncOperation<TResult> 인터페이스

리턴 값이 있는 비동기 작업을 지원한다.


* IAsyncOperationWithProgress<TResult, TProgress> 인터페이스

리턴 값이 있고, 진행 상황을 표시할 수 있는 프로그래세를 지원한다.


참고 링크

http://msdn.microsoft.com/ko-kr/library/windows/apps/br211924.aspx

 

위의 4개 중 3번째에 있는 IAsyncOperation을 이용해서 메시지 박스를 만들어 보자

 

2. SimpleConfirmBox.xaml

간단하게 UserControl를 이용해서 UI를 만들어 준다.

 

* Popup에 넣어서 사용하기 때문에 크기 계산을 위해 Height, Width를 입력했다.

* ViewModel은 화면이 생성되면서 함께 만들어 진다.

* ListBox의 ItemsPanel을 수정해서 가로로 표시 되도록 했다.

* ViewModel과의 Binding을 잘 살펴 본다.

 

<UserControl
    x:Class="PushpinSample.SimpleConfirmBox"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:PushpinSample"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Height="200"
    Width="400"
>
   
    <UserControl.DataContext>
        <local:SimpleConfirmBoxViewModel/>
    </UserControl.DataContext>

 

    <Grid Background="Gray">
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition Height="31*"/>
            <RowDefinition Height="50"/>
        </Grid.RowDefinitions>

 

        <TextBlock Text="{Binding Title}" Style="{StaticResource HeaderTextStyle}"/>
        <Border Grid.Row="1" Background="DarkGray" >
            <TextBlock Text="{Binding Message}" Style="{StaticResource ItemTextStyle}"/>
        </Border>
       
        <ListBox Grid.Row="2" ItemsSource="{Binding Buttons}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" HorizontalAlignment="Right">
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
        </ListBox>
    </Grid>
</UserControl>

3. SimpleConfirmBoxViewModel.cs

* ListBox의 SelectedItem과 바인딩이 되어있다.

* SelectedItem 프로퍼티가 변경되었을 때 Parent에 결과를 저장하고 팝업을 닫아 준다.

 

    public class SimpleConfirmBoxViewModel : PushpinSample.Common.BindableBase
    {
        public Popup Parent { get; set; }

        public string Title { get; set; }

        public string Message { get; set; }

        public IList<string> Buttons { get; set; }

 

        private string _selectedItem;
        /// <summary>
        /// Selected Item Test
        /// </summary>
        public string SelectedItem
        {
            get { return _selectedItem; }
            set { SetProperty(ref _selectedItem, value); }
        }

 

        public SimpleConfirmBoxViewModel()
        {
            if (Windows.ApplicationModel.DesignMode.DesignModeEnabled == true)
            {
                Title = "Test Title";
                Message = "Select your text";
                Buttons = new List<string>
                    {
                        "Test1",
                        "Test2",
                        "Test3",
                    };
            }
            else
            {
                this.PropertyChanged +=
                    (s, e) =>
                    {
                        switch (e.PropertyName)
                        {
                            case "SelectedItem":
                                if (SelectedItem != null)
                                {
                                    Parent.Resources.Add("Result", SelectedItem);
                                    Parent.IsOpen = false;
                                }
                                break;
                        }
                    };
            }
        }

    }

 

4. SimpleConfirmBox Method

 

        /// <summary>
        /// Simple ConfirmBox
        /// </summary>
        public Windows.Foundation.IAsyncOperation<string> SimpleConfirmBox(string title, string message, IList<string> buttons)
        {
            var bounds = Windows.UI.Xaml.Window.Current.CoreWindow.Bounds;

 

            //buttons가 null이면 바로 종료
            if (buttons == null)
            {
                return AsyncInfo.Run<string>(_ => Task.Run<string>(() => string.Empty) );
            }

 

            popup = popup ?? new Windows.UI.Xaml.Controls.Primitives.Popup();

            //UI 생성
            var content = new SimpleConfirmBox();

          //ViewModel
            var viewModel = (SimpleConfirmBoxViewModel)content.DataContext;
             //프로퍼티 설정

            viewModel.Title = title;
            viewModel.Message = message;
            viewModel.Buttons = buttons;

            viewModel.Parent = popup;
            //위치지정

            popup.VerticalOffset = (bounds.Height - content.Height) / 2;
            popup.HorizontalOffset = (bounds.Width - content.Width) / 2;
            popup.Child = content;

            //팝업이 닫혔을 때 이벤트 등록
            popup.Closed +=
                (s, e) =>
                {
                    object result;

                    //결과 확인
                    if (popup.Resources.TryGetValue("Result", out result) == true)
                    {

                        //task 종료
                        _taskCompletionSource.TrySetResult(result.ToString());
                    }
                    if (popup != null) popup = null;
                };

            //팝업 열기
            popup.IsOpen = true;

            //task 생성, 완료 될 때까지 대기

            return System.Runtime.InteropServices.WindowsRuntime.AsyncInfo.Run(token => WaitForClose(token));
        }

 

        //작업 완료 소스

        private System.Threading.Tasks.TaskCompletionSource<string> _taskCompletionSource;

 

        //작업 완료 테스크

        private System.Threading.Tasks.Task<string> WaitForClose(System.Threading.CancellationToken token)
        {
            _taskCompletionSource = new System.Threading.Tasks.TaskCompletionSource<string>();

            //취소 처리 등록
            token.Register(() =>
            {
                //CancelTokenRegister
                popup.IsOpen = false;
                _taskCompletionSource.SetCanceled();
                popup = null;
            });
            return _taskCompletionSource.Task;
        }

 

5. 사용하기

 

        private async void pushpinTapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
        {
            var result = await SimpleConfirmBox("Confirm", "Select your phone", new List<string> { "Windows Phone", "iPhone", "Android", "Etc" });
            MessageDialog dialog = new MessageDialog(string.Format("Your phone is {0}", result), "Information");
            await dialog.ShowAsync();
        }

 

 

 

 

반응형
댓글