티스토리 뷰

반응형

눈인지 비인지 알 수 없는 넘(?)들이 하늘에서 내려오는 날이다. 이렇게 좋은 날 행복한 망고 강좌 5번의 시작을 장식해서 살짝 흥분된다. 흐흐;;; 이번 강좌에서는 컨버터를 만들어서 사용하는 방법과 오류 처리와 네비게이션에 대해 간단하게 정리하고 넘어가도록 하겠다.

1. Converter만들기
우리가 필요한 건 routeType을 가지고 택스트 데이터를 반환하는 것과 routeType과 동일한 컬러를 반환하는 2가지의 컨버터를 만들 것이다.

VS2010에서 작업

Converters 폴더 선택 -> Add -> Class -> RouteTypeToColorConverter.cs
Converters 폴더 선택 -> Add -> Class -> RouteTypeToNameConverter.cs
이렇게 2개를 추가해 놓고 먼저 RouteTypeToNameConverter.cs를 먼저 만들어보자

using System;
using System.Windows.Data;

namespace BusInfo.Converters
{
    public class RouteTypeToNameConverter : IValueConverter
    {
        //코드를 텍스트로
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            //컨버터로 넘어오는 데이터를 숫자형으로 변경
            int routeType = System.Convert.ToInt32(value);
            //반환될 데이터를 문자형으로 생성
            string returnValue = string.Empty;

            //노선 유형(1:공항, 3:간선, 4:지선, 5:순환, 6:광역, 7:인천, 8:경기, 9:폐지, 0:공용)
            switch (routeType)
            {
                case 0:
                    returnValue = "공용";
                    break;
                case 1:
                    returnValue = "공항";
                    break;
                case 3:
                    returnValue = "간선";
                    break;
                case 4:
                    returnValue = "지선";
                    break;
                case 5:
                    returnValue = "순환";
                    break;
                case 6:
                    returnValue = "광역";
                    break;
                case 7:
                    returnValue = "인천";
                    break;
                case 8:
                    returnValue = "경기";
                    break;
                case 9:
                    returnValue = "폐지";
                    break;
            }
            return returnValue;
        }

        //반대의 경우 처리하는 코드를 쓰는 부분인데..요기서는 필요 없다
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

다음은 컬러 RouteTypeToColorConverter.cs

using System;
using System.Windows.Data;
using System.Windows.Media;

namespace BusInfo.Converters
{
    public class RouteTypeToColorConverter : IValueConverter
    {
        //코드를 브러쉬로
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            //컨버터로 넘어오는 데이터를 숫자형으로 변경
            int routeType = System.Convert.ToInt32(value);
            //반환될 데이터를 브러쉬로 생성
            Brush returnValue;

            //노선 유형(1:공항, 3:간선, 4:지선, 5:순환, 6:광역, 7:인천, 8:경기, 9:폐지, 0:공용)
            switch (routeType)
            {
                case 1:
                    returnValue = new SolidColorBrush(Colors.Orange);
                    break;
                case 3:
                    returnValue = new SolidColorBrush(Colors.Blue);
                    break;
                case 4:
                    returnValue = new SolidColorBrush(Colors.Green);
                    break;
                case 7:
                    returnValue = new SolidColorBrush(Colors.Magenta);
                    break;
                case 8:
                    returnValue = new SolidColorBrush(Colors.Red);
                    break;
                default:
                    returnValue = new SolidColorBrush(Colors.White);
                    break;
            }

            return returnValue;
        }

        //반대의 경우 처리하는 코드를 쓰는 부분인데..요기서는 필요 없다
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

F6 눌러서 빌드 후에 블랜드로 이동

상단에  [ ListBox ] -> Edit Additional Templetes -> Edit Generated Items (ItemTemplate) -> Edit Current 클릭


RouteType이 바인딩 되어있는 TextBlock를 선택 -> Text 프로퍼티 오른쪽에 노란색 네모 클릭 -> Data Binding 클릭

요기까지 나오게 한 다음에
Value converter 오른쪽에 [...] 버튼을 클릭 ->

RouteTypeToNameConverter 선택 -> OK -> OK
컨버터 적용하는 것도 매우 간단하다는 것을 알 수 있다.

이번에는 Border에 유형별 색상을 적용시켜 보자. (BorderThickness는 적당한 값으로 설정한다.)
Border를 선택 ->오른쪽 Brushes -> BorderBrush 프로퍼티 오른쪽에 네모 클릭 -> Data Binding 선택 ->


Show -> All Properties -> RouteType 선택 -> 역삼각형 모양 클릭해서 아래 넓히고 ->
Value converter 오른쪽에 […] 클릭 -> RouteTypeToColorConverter선택 - Ok

위의 상태까지 동일하면 Ok눌러서 바인딩 완료

데이터 템플릿의 최종 소스

<ResourceDictionary
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:BusInfo_Converters="clr-namespace:BusInfo.Converters">

 <BusInfo_Converters:RouteTypeToColorConverter x:Key="RouteTypeToColorConverter"/>
 <!-- Resource dictionary entries should be defined here. -->
 <BusInfo_Converters:RouteTypeToNameConverter x:Key="RouteTypeToNameConverter"/>
 
 <DataTemplate x:Key="BusRouteDataTemplate">
  <Border BorderThickness="10,1,0,0" Width="450" BorderBrush="{Binding RouteType, Converter={StaticResource RouteTypeToColorConverter}}" >
   <Grid>
    <Grid.RowDefinitions>
     <RowDefinition Height="0.5*"/>
     <RowDefinition Height="0.5*"/>
    </Grid.RowDefinitions>
    <StackPanel Orientation="Horizontal">
     <TextBlock TextWrapping="Wrap" Text="◎ 종류 : "/>
     <TextBlock TextWrapping="Wrap" Text="{Binding RouteType, Converter={StaticResource RouteTypeToNameConverter}}"/>
     <TextBlock TextWrapping="Wrap" Text="◎ 버스명 : " Margin="6,0,0,0"/>
     <TextBlock TextWrapping="Wrap" Text="{Binding BusRouteNm}" />
    </StackPanel>
    <StackPanel Grid.Row="1" Orientation="Horizontal">
     <TextBlock TextWrapping="Wrap" Text="◎ 노선 : "/>
     <TextBlock Text="{Binding StartStationNm}"/>
     <TextBlock TextWrapping="Wrap" Text=" ~ "/>
     <TextBlock Text="{Binding EndStationNm}"/>
    </StackPanel>
   </Grid>
  </Border>
 </DataTemplate>
</ResourceDictionary>

이렇게만 만들고 실행하면 ListBox에 구분선이 없어서 좀 허전한 느낌이 든다.
그래서 ListBox도 Border로 감싸고 색을 좀 주고, 노선번호 입력하는 텍스트박스는 숫자만 입력이 가능하면 되기 때문에 그 부분도 약간 손을 본다.
 MainPage.xaml의 최종 소스는 아래와 같다.

<phone:PhoneApplicationPage
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:BusInfo_ViewModels="clr-namespace:BusInfo.ViewModels"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    x:Class="BusInfo.MainPage"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">
 
    <!--Sample code showing usage of ApplicationBar-->
    <!--<phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
            <shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="Button 1"/>
            <shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" Text="Button 2"/>
            <shell:ApplicationBar.MenuItems>
                <shell:ApplicationBarMenuItem Text="MenuItem 1"/>
                <shell:ApplicationBarMenuItem Text="MenuItem 2"/>
            </shell:ApplicationBar.MenuItems>
        </shell:ApplicationBar>
    </phone:PhoneApplicationPage.ApplicationBar>-->

 <d:DataContext>
  <BusInfo_ViewModels:MainPageViewModel/>
 </d:DataContext>

    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--TitlePanel contains the name of the application and page title-->
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock x:Name="ApplicationTitle" Text="kaki104 App" Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="PageTitle" Text="버스 목록 조회" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}" FontSize="64" />
        </StackPanel>

        <!--ContentPanel - place additional content here-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
         <Grid.RowDefinitions>
          <RowDefinition Height="72"/>
          <RowDefinition/>
         </Grid.RowDefinitions>
         <StackPanel Orientation="Horizontal">
          <TextBlock TextWrapping="Wrap" Text="노선번호" VerticalAlignment="Center"/>
          <TextBox TextWrapping="Wrap" Text="{Binding SBusNum, Mode=TwoWay}" Width="275" InputScope="Number"/>
          <Button Content="조회">
           <i:Interaction.Triggers>
            <i:EventTrigger EventName="Click">
             <i:InvokeCommandAction Command="{Binding GetBusRouteListCommand, Mode=OneWay}"/>
            </i:EventTrigger>
           </i:Interaction.Triggers>
          </Button>
         </StackPanel>
         <Border Grid.Row="1" BorderThickness="1" BorderBrush="White" >
          <ListBox ItemTemplate="{StaticResource BusRouteDataTemplate}" ItemsSource="{Binding BusRouteCollection}"/>
         </Border>
        </Grid>
    </Grid>

</phone:PhoneApplicationPage>

작업이 완료된 후에 실행해서 결과를 확인 하자


컨버터를 이용해서 노선 유형을 택스트로 변경하고, 색까지 표현하도록 만들어 보았다.

2. 오류 처리를 하나 추가해 보자

앱을 실행하고 바로 번호를 입력하지 않은 상태에서 조회를 눌러보자

GetBusRouteListCommand에 있는
if (SBusNum.Length <= 1)
{
    MessageBox.Show("2글자 이상 입력해야 합니다.");
    return;
}
이 부분에서 오류가 발생한다. SbusNum이 Null값을 가지기 때문에 Length를 알 수 없기 때문이니..
간단하게 수정을 하자

if (SBusNum == null || SBusNum.Length <= 1)
{
    MessageBox.Show("2글자 이상 입력해야 합니다.");
    return;
}

3. 네비게이션 기능 추가
네비게이션이 무엇인지는 다들 알고 있을 것이라고 생각하고, 설명은 하지 않겠다. 여기서는 윈도우 폰의 페이지에서 어떻게 네비게이션 처리를 하는지만 알아 보도록 하자.
기본적인 네비게이션 서비스는 View에서만 적용이 가능한데, 이 것을 뷰모델에서 가능하도록 코드를 추가해 주어야한다. 우선, MainPageViewModel.cs 뷰모델에 추가 작업을 한다.

//메인 프레임
PhoneApplicationFrame root;
그리고, 커맨드를 하나 추가한다. 커맨드 이름은 SelectionChangedCommand이다.

private ICommand selectionChangedCommand;
/// <summary>
/// 노선 목록에서 선택된 아이템이 변경된 경우 실행되는 커맨드
/// </summary>
public ICommand SelectionChangedCommand
{
    get
    {
        if (selectionChangedCommand == null)
        {
            selectionChangedCommand = new ActionCommand(() =>
            {
                //메인 프레임 입력 - 네비게이션하는데 필요
                if (root == null)
                {
                    //생성자에서는 이 데이터를 가지고 올 수가 없음..
                    root = App.Current.RootVisual as PhoneApplicationFrame;
                }
                //Uri에 있는 xaml파일은 조금 있다 추가한다.
                root.Navigate(new Uri("/Views/StationByRouteView.xaml", UriKind.Relative));
            });
        }
        return selectionChangedCommand;
    }
}

이제 프로젝트에 Views폴더 선택 -> Add -> New Item -> Windows Phone Portrait Page -> Name : StationByRouteView.xaml -> OK
F6을 눌러서 빌드를 한번 하고, 블랜드로 넘어가서

MainPage.xaml에 있는 ListBox에 ListBox에 InvokeCommandAction을 추가한다. (추가하는 방법은 3회 강좌를 참고한다.)
추가한 InvokeCommandAction를 선택하고 오른쪽 상단 EventName을 SelectionChanged 이벤트를 선택하고 Command 프로퍼티 오른쪽에 하드 디스크 모양 아이콘을 눌러서 Create Data Binding에서 SelectionChangedCommand를 선택하고 OK를 누른다. (저장도 꼭)


저장 까지 완료 한 상태의 화면

4. 최종 테스트


105번 선택

네비게이션 서비스 까지 완료된 것을 확인 할 수 있다.

6. 여기까지 했으니 이제 절반은 완성 한 것 같다.
만드는 방법을 자세하게 한다고 했는데.. 잘 되었는지 모르겠다. 질문은 리플로 남겨 주기 바란다

반응형

'Previous Platforms > KBI' 카테고리의 다른 글

Seoul Bus Info Search App Dev 7  (0) 2012.01.07
Seoul Bus Info Search App Dev 6  (0) 2012.01.07
Seoul Bus Info Search App Dev 4  (0) 2012.01.07
Seoul Bus Info Search App Dev 3  (0) 2012.01.04
Seoul Bus Info Search App Dev 2  (0) 2012.01.04
댓글