블로그 이미지
* Microsoft MVP - Windows Development 2014 ~ 2020 http://youtube.com/FutureOfDotNet kaki104

카테고리

List All (607)
Visual Studio (7)
Blazor (2)
Windows App(Universa.. (104)
Xamarin Forms (4)
Bot Framework (19)
Azure (9)
Windows 10 (53)
WPF (7)
Facebook News & Tips (158)
Windows 8&8.1 (113)
Windows Phone 8 (42)
Silverlight (37)
HTML5 & MVC4 (16)
Portable Class Library (2)
Uncategorised Tips a.. (3)
Kinect for Windows (2)
ETC (12)
kaki104 Scrap (4)
App News (11)
Total548,251
Today7
Yesterday33

2012년 윈도우 폰이 잘 되어서.. 개발자들이 기를 펴고 살 수 있기를 기원하며..오늘의 강좌를 시작해 보자.
6번째 강좌에서는 선택된 버스의 정류장 정보를 조회해서 2번째 페이지에 출력하는 부분까지 진행을 하도록 하겠다.

1. 노선별 경유 정류소 목록 조회
(http://api.bus.go.kr/contents/sub02/getStaionByRoute.html)
(페이지의 내용 + 실제 데이터를 확인 한 후 모델을 작성하면 된다.)

StationByRouteModel.cs

using System.ComponentModel;

namespace BusInfo.Models
{
    //http://api.bus.go.kr/contents/sub02/getStaionByRoute.html
    //노선별 경유 정류소 목록 조회
    public class StationByRouteModel : INotifyPropertyChanged
    {
        #region PropertyChange
        public event PropertyChangedEventHandler PropertyChanged;

        private void FirePropertyChange(string PropertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
            }
        }
        #endregion

        private string beginTm;
        /// <summary>
        /// 첫차시간
        /// </summary>
        public string BeginTm
        {
            get { return beginTm; }
            set
            {
                beginTm = value;
                FirePropertyChange("BeginTm");
            }
        }

        string lastTm;
        /// <summary>
        /// 막차시간
        /// </summary>
        public string LastTm
        {
            get { return lastTm; }
            set
            {
                lastTm = value;
                FirePropertyChange("LastTm");
            }
        }

        int busRouteId;
        /// <summary>
        /// 노선ID
        /// </summary>
        public int BusRouteId
        {
            get { return busRouteId; }
            set
            {
                busRouteId = value;
                FirePropertyChange("BusRouteId");
            }
        }

        string busRouteNm;
        /// <summary>
        /// 노선명
        /// </summary>
        public string BusRouteNm
        {
            get { return busRouteNm; }
            set
            {
                busRouteNm = value;
                FirePropertyChange("BusRouteNm");
            }
        }

        double gpsX;
        /// <summary>
        /// X좌표 WGS 84
        /// </summary>
        public double GpsX
        {
            get { return gpsX; }
            set
            {
                gpsX = value;
                FirePropertyChange("GpsX");
            }
        }

        double gpsY;
        /// <summary>
        /// Y좌표 WGS 84
        /// </summary>
        public double GpsY
        {
            get { return gpsY; }
            set
            {
                gpsY = value;
                FirePropertyChange("GpsY");
            }
        }

        int routeType;
        /// <summary>
        /// 노선유형
        /// </summary>
        public int RouteType
        {
            get { return routeType; }
            set
            {
                routeType = value;
                FirePropertyChange("RouteType");
            }
        }

        int section;
        /// <summary>
        /// 구간
        /// </summary>
        public int Section
        {
            get { return section; }
            set
            {
                section = value;
                FirePropertyChange("Section");
            }
        }

        int seq;
        /// <summary>
        /// 순번
        /// </summary>
        public int Seq
        {
            get { return seq; }
            set
            {
                seq = value;
                FirePropertyChange("Seq");
            }
        }

        int station;
        /// <summary>
        /// 정류소ID
        /// </summary>
        public int Station
        {
            get { return station; }
            set
            {
                station = value;
                FirePropertyChange("Station");
            }
        }

        string stationNm;
        /// <summary>
        /// 정류소명
        /// </summary>
        public string StationNm
        {
            get { return stationNm; }
            set
            {
                stationNm = value;
                FirePropertyChange("StationNm");
            }
        }

        int stationNo;
        /// <summary>
        /// 정류소 고유번호
        /// </summary>
        public int StationNo
        {
            get { return stationNo; }
            set
            {
                stationNo = value;
                FirePropertyChange("StationNo");
            }
        }

        float fullSectDist;
        /// <summary>
        /// 정류소간 거리
        /// </summary>
        public float FullSectDist
        {
            get { return fullSectDist; }
            set
            {
                fullSectDist = value;
                FirePropertyChange("FullSectDist");
            }
        }

        int trnstnId;
        /// <summary>
        /// 회차지정류소ID
        /// </summary>
        public int TrnstnId
        {
            get { return trnstnId; }
            set
            {
                trnstnId = value;
                FirePropertyChange("TrnstnId");
            }
        }
    }
}

F6키를 눌러서 빌드를 한번 해주고 MainPageViewModel.cs로 이동한다.

2. MainPageViewModel.cs 수정
정류소 목록을 저장할 컬렉션 프로퍼티를 하나 추가하고

ObservableCollection<StationByRouteModel> stationCollection;
/// <summary>
/// 노선별 경유 정류소 컬렉션 - 프로퍼티
/// </summary>
public ObservableCollection<StationByRouteModel> StationCollection
{
    get { return stationCollection; }
    set
    {
        stationCollection = value;
        FirePropertyChange("StationCollection");
    }
}

SelectionChangedCommand를 수정한다.
(네비게이션 서비스는 정류소 목록이 완성이 된 후에 넘어가야 하기 때문에 현재 커맨드 내부에 있는 네비게이션은 일단 삭제해 준다)
그리고, 정류소 조회 OpenAPI를 호출한다.

private ICommand selectionChangedCommand;
/// <summary>
/// 노선 목록에서 선택된 아이템이 변경된 경우 실행되는 커맨드
/// </summary>
public ICommand SelectionChangedCommand
{
    get
    {
        if (selectionChangedCommand == null)
        {
            selectionChangedCommand = new ActionCommand(item =>
            {
                //메인 프레임 입력 - 네비게이션하는데 필요
                if (root == null)
                {
                    //생성자에서는 이 데이터를 가지고 올 수가 없음..
                    root = App.Current.RootVisual as PhoneApplicationFrame;
                }

                //커맨드 파라메터로 전달 받은 오브젝트를 형변환
                BusRouteModel route = item as BusRouteModel;
                //형변환을 성공적으로 처리했다면
                if (route != null)
                {
                    //정류소 조회
                    var uri = new Uri("http://ws.bus.go.kr/api/rest/busRouteInfo/getStaionByRoute?ServiceKey=" + SKey.BusRouteInfo + "&busRouteId=" + route.BusRouteId);
                    wc.DownloadStringAsync(uri, "GetStaionByRoute");
                }

            });
        }
        return selectionChangedCommand;
    }
}

3. 블랜드로 전환 디자인 수정 - 커맨드 파라메터 추가
ListBox에 있는 InvokeCommandAction에 CommandParameter를 추가한다.  InvokeCommandAction에는 1개의 CommandParameter 입력이 가능하고, 선택된 파라메터 데이터는 뷰모델에 SelectionChangedCommand로 넘어 item에 담기게 된다.

InvokeCommandAction선택 -> 오른쪽 상단 프로퍼티에서 CommandParameter 오른쪽에 네모 클릭 -> Data Binding 선택 -> Element Property 텝 선택 -> Scene elements에서 ListBox 선택 -> Properties에서 SelectedItem 선택 -> OK


이렇게 입력을 한 후에 xaml을 확인 해보자

<ListBox x:Name="listBox" ItemTemplate="{StaticResource BusRouteDataTemplate}" ItemsSource="{Binding BusRouteCollection}">
 <i:Interaction.Triggers>
  <i:EventTrigger EventName="SelectionChanged">
   <i:InvokeCommandAction Command="{Binding SelectionChangedCommand, Mode=OneWay}" CommandParameter="{Binding SelectedItem, ElementName=listBox}"/>
  </i:EventTrigger>
 </i:Interaction.Triggers>
</ListBox>

CommandParameter로 listBox에 SelectedItem을 넘기도로 수정이 되어 있는 것을 볼 수 있다.
왜 SelectedItem을 파라메터로 넘기는 것일까? 우리는 MVVM 패턴을 사용하고, Object 프로그램을 하고 있으니 충분히 알 수 있을 것이라 생각한다.

4. VS2010으로 돌아와서 오퍼레이션 확인
wc.DownloadStringAsync(uri, "GetStaionByRoute"); //브레이크를 걸고 디버그 모드로 실행을 해보자
route에 데이터를 확인을 해보면 우리가 선택한 노선의 데이터가 들어가 있는 것을 확인 할 수 있다.

5. 정류소 조회 데이터 파싱
wc_DownloadStringCompleted 이벤트 처리 부를 수정한다.

case "GetStaionByRoute":
    //정류소 목록 파싱
    var stations = from item in xml.Descendants("itemList")
                   select new StationByRouteModel
                   {
                       BusRouteId = Convert.ToInt32(item.Element("busRouteId").Value),
                       BusRouteNm = item.Element("busRouteNm").Value,
                       Seq = Convert.ToInt32(item.Element("seq").Value),
                       Section = Convert.ToInt32(item.Element("section").Value),
                       Station = Convert.ToInt32(item.Element("station").Value),
                       StationNm = item.Element("stationNm").Value,
                       GpsX = Convert.ToDouble(item.Element("gpsX").Value),
                       GpsY = Convert.ToDouble(item.Element("gpsY").Value),
                       FullSectDist = Convert.ToSingle(item.Element("fullSectDist").Value),
                       StationNo = Convert.ToInt32(item.Element("stationNo").Value),
                       RouteType = Convert.ToInt32(item.Element("routeType").Value),
                       BeginTm = item.Element("beginTm").Value,
                       LastTm = item.Element("lastTm").Value,
                       TrnstnId = Convert.ToInt32(item.Element("trnstnid").Value)
                   };
    StationCollection = new ObservableCollection<StationByRouteModel>(stations);
    break;

디버그 모드로 실행해서 StationCollection에 데이터가 잘 들어와 지는지 확인 해보자. 정상적으로 데이터가 들어와 있으면 이제 페이지를 변경하고 그 페이지에 데이터를 보여주면 되는 것이다.

6. MVVM에서..
지금까지 사용해 본 경험에 의하면 View와 ViewModel은 1:1 관계를 이루는 것이 가장 심플하다. 하나의 뷰모델을 여러개의 뷰가 사용을 하게되면 복잡도가 올라가서 나중에 디버그 하기가 용이하지 않기 때문인데..그러나, 이 프로젝트에서는 하나의 뷰모델을 2개의 뷰에서 공유해서 사용하도록 하겠다.(여러가지 이유가..흐흐)

1개의 뷰모델을 공유해서 사용하는 방법은.. MEF가 가능한 Silverlight라면 문제가 되지 않치만 WP에서는 MEF를 지원하지 않기 때문에 약간 다른 방법(?)을 사용해서 처리 했는데... 그 방법은 격리저장소(IsolatedStorage)를 사용하는 것이다. 네비게이션 서비스는 String 파라메터를 넘길 수는 있지만 Object 파라메터를 넘길 수는 없기 때문이다.
(구글에서 찾아보면 Interface를 추가해서 사용하는 방법이 있기는 하지만..지금 쉽게 접근하지는 못할 것 같아서 다루지 않는다. 쉽게 Object를 넘길 수 있는 방법이 있으면 알려주기 바란다. 이 방법은 독자적으로 생각나서 만들어 본 것으로 찾아 보지는 않았다...혹시 있을지도..쿨럭)

Functions폴더에 StaticFunctions.cs 파일을 추가하고 코딩을 해보자

using System.IO.IsolatedStorage;

namespace BusInfo.Functions
{
    public static class StaticFunctions
    {
        /// <summary>
        /// 내부저장소에 데이터 저장
        /// </summary>
        /// <param name="key">키</param>
        /// <param name="data">데이터</param>
        /// <returns></returns>
        public static bool SaveToIS(string key, object data)
        {
            if (IsolatedStorageSettings.ApplicationSettings.Contains(key) == false)
            {
                IsolatedStorageSettings.ApplicationSettings.Add(key, data);
            }
            else
            {
                IsolatedStorageSettings.ApplicationSettings[key] = data;
            }
            return true;
        }

        /// <summary>
        /// 내부저장소에서 데이터 조회
        /// </summary>
        /// <param name="key">키</param>
        /// <returns>데이터</returns>
        public static object LoadFromIS(string key)
        {
            object data;
            if (IsolatedStorageSettings.ApplicationSettings.Contains(key) == false)
            {
                data = null;
            }
            else
            {
                data = IsolatedStorageSettings.ApplicationSettings[key];
            }

            return data;
        }
    }
}

그리고, MainPageViewModel.cs를 다시 수정한다.

case "GetStaionByRoute":
    //정류소 목록 파싱
    var stations = from item in xml.Descendants("itemList")
                   select new StationByRouteModel
                   {
                       BusRouteId = Convert.ToInt32(item.Element("busRouteId").Value),
                       BusRouteNm = item.Element("busRouteNm").Value,
                       Seq = Convert.ToInt32(item.Element("seq").Value),
                       Section = Convert.ToInt32(item.Element("section").Value),
                       Station = Convert.ToInt32(item.Element("station").Value),
                       StationNm = item.Element("stationNm").Value,
                       GpsX = Convert.ToDouble(item.Element("gpsX").Value),
                       GpsY = Convert.ToDouble(item.Element("gpsY").Value),
                       FullSectDist = Convert.ToSingle(item.Element("fullSectDist").Value),
                       StationNo = Convert.ToInt32(item.Element("stationNo").Value),
                       RouteType = Convert.ToInt32(item.Element("routeType").Value),
                       BeginTm = item.Element("beginTm").Value,
                       LastTm = item.Element("lastTm").Value,
                       TrnstnId = Convert.ToInt32(item.Element("trnstnid").Value)
                   };
    StationCollection = new ObservableCollection<StationByRouteModel>(stations);

    //정류소 목록 조회 화면으로 네비게이션
    root.Navigate(new Uri("/Views/StationByRouteView.xaml", UriKind.Relative));
    break;

MainPageViewModel 생성자에 추가

    //격리 저장소에 뷰모델을 저장
    StaticFunctions.SaveToIS("MainPageViewModel", this);


7. 블랜드에서 정류소 목록 페이지를 디자인 해보자


(혼자서 열심히 그려보도록 하자 : 하단은 ListBox이고 Border로 감싼 후 주위를 흰색으로 처리 했다.)
이제 DataContext를 붙여야 한다. 붙이는 방법은 MainPage.xaml에서 사용했던 방법과 동일하게 처리하면 된다.(모른다고 하면 때림^^;;;)
그리고, ListBox를 선택하고 -> ItemsSource 프로퍼티 오른쪽에 네모를 클릭해서 -> Data Binding -> StationCollection -> OK
지금까지의 StationByRouteView.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"
    x:Class="BusInfo.Views.StationByRouteView"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
    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">
         <Border BorderThickness="1" BorderBrush="White">
          <ListBox ItemsSource="{Binding StationCollection}"/>
         </Border>
        </Grid>
    </Grid>

</phone:PhoneApplicationPage>

여기까지만 하면 디자인 타임에 MainPageViewModel.cs에 있는 프로퍼티를 사용하는 것은 문제가 없다. 하지만, 런타임에는 아무것도 나오지 않는다. StationByRouteView.xaml.cs에 추가로 코딩을 하자.

8. StationByRouteView.xaml.cs

using BusInfo.Functions;
using BusInfo.ViewModels;
using Microsoft.Phone.Controls;

namespace BusInfo.Views
{
    public partial class StationByRouteView : PhoneApplicationPage
    {
        //뷰모델을 프로퍼티로 선언하고
        public MainPageViewModel ViewModel { get; set; }

        /// <summary>
        /// 생성자
        /// </summary>
        public StationByRouteView()
        {
            InitializeComponent();

            //격리 저장소에 있는 뷰모델을 불러와서 뷰모델에 넣고
            ViewModel = StaticFunctions.LoadFromIS("MainPageViewModel") as MainPageViewModel;
            //뷰모델을 데이터컨텍스트에 입력
            this.DataContext = ViewModel;
        }
    }
}

여기까지 코딩 후 실행 한다.


선택한 버스의 정류소 목록들이 표시(?)가 되었다. 위와 같이 나오는 것은 바인딩 되어있는 모델의 이름이 보이고 있는 것이다.
일단은 정류소 이름이라도 보이도록 처리해보자.

블랜드에서 ListBox를 선택 후 DisplayMemberPath 프로퍼티에 StationNm이라고 입력한다.(이건 바인딩이 아니다 직접 입력한다). 그리고 다시 실행 해 본다. 3100안산 버스를 클릭 후
 


<- 버튼을 눌러서 뒤로 돌아간 후 3100의정부 버스를 클릭 했다.
 

정류소 목록이 변경되는 것을 알 수 있다.

여기서 의문을 가져야 하는 부분이 한가지 있다. 과연 MainPageViewModel은 어떻게 된 것일까?
MainPage.xaml의 생성자에서 한번 저장해주고, StationByRouteView.xaml의 생성자에서 한번 불러왔을 뿐인데..어떻게..
그건 여러분의 몫으로 남겨 두겠다.

MainPageViewModel.cs 전체 소스

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Input;
using System.Xml.Linq;
using BusInfo.Functions;
using BusInfo.Models;
using Microsoft.Expression.Interactivity.Core;
using Microsoft.Phone.Controls;

namespace BusInfo.ViewModels
{
    public class MainPageViewModel : INotifyPropertyChanged
    {
        #region PropertyChange
        public event PropertyChangedEventHandler PropertyChanged;

        private void FirePropertyChange(string PropertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
            }
        }
        #endregion

        /// <summary>
        /// 검색할 버스 노선 번호
        /// </summary>
        public string SBusNum { get; set; }

        /// <summary>
        /// 웹 클라이언트
        /// </summary>
        WebClient wc;

        /// <summary>
        /// 인증 키
        /// </summary>
        ServiceKey SKey;

        ObservableCollection<BusRouteModel> busRouteCollection;
        /// <summary>
        /// 버스 목록 컬렉션 - 프로퍼티
        /// </summary>
        public ObservableCollection<BusRouteModel> BusRouteCollection
        {
            get { return busRouteCollection; }
            set
            {
                busRouteCollection = value;
                FirePropertyChange("BusRouteCollection");
            }
        }

        ObservableCollection<StationByRouteModel> stationCollection;
        /// <summary>
        /// 노선별 경유 정류소 컬렉션 - 프로퍼티
        /// </summary>
        public ObservableCollection<StationByRouteModel> StationCollection
        {
            get { return stationCollection; }
            set
            {
                stationCollection = value;
                FirePropertyChange("StationCollection");
            }
        }

        //메인 프레임
        PhoneApplicationFrame root;

        /// <summary>
        /// 생성자
        /// </summary>
        public MainPageViewModel()
        {
            //웹클라이언트 생성
            wc = new WebClient();
            wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);
            //서비스키 생성
            SKey = new ServiceKey();

            //격리 저장소에 뷰모델을 저장
            StaticFunctions.SaveToIS("MainPageViewModel", this);
        }

        /// <summary>
        /// 웹클라이언트 다운로드스트링 컴플릿트 이벤트 구현
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            if (e.Error != null)
                return;
            //xml을 xElement라는 객체로 바로 파싱해서 사용한다.
            XElement xml = XElement.Parse(e.Result);
            //어떤 서비스의 결과인지에 따라서 각각 다른 처리를 한다.
            switch (e.UserState as string)
            {
                case "GetBusRouteList":
                    //버스 노선 목록 파싱
                    var rows = from item in xml.Descendants("itemList")
                               select new BusRouteModel
                               {
                                   BusRouteId = Convert.ToInt32(item.Element("busRouteId").Value),
                                   BusRouteNm = item.Element("busRouteNm").Value,
                                   StartStationNm = item.Element("stStationNm").Value,
                                   EndStationNm = item.Element("edStationNm").Value,
                                   RouteType = Convert.ToInt32(item.Element("routeType").Value),
                                   Term = Convert.ToInt32(item.Element("term").Value)
                               };
                    BusRouteCollection = new ObservableCollection<BusRouteModel>(rows);

                    break;
                case "GetStaionByRoute":
                    //정류소 목록 파싱
                    var stations = from item in xml.Descendants("itemList")
                                   select new StationByRouteModel
                                   {
                                       BusRouteId = Convert.ToInt32(item.Element("busRouteId").Value),
                                       BusRouteNm = item.Element("busRouteNm").Value,
                                       Seq = Convert.ToInt32(item.Element("seq").Value),
                                       Section = Convert.ToInt32(item.Element("section").Value),
                                       Station = Convert.ToInt32(item.Element("station").Value),
                                       StationNm = item.Element("stationNm").Value,
                                       GpsX = Convert.ToDouble(item.Element("gpsX").Value),
                                       GpsY = Convert.ToDouble(item.Element("gpsY").Value),
                                       FullSectDist = Convert.ToSingle(item.Element("fullSectDist").Value),
                                       StationNo = Convert.ToInt32(item.Element("stationNo").Value),
                                       RouteType = Convert.ToInt32(item.Element("routeType").Value),
                                       BeginTm = item.Element("beginTm").Value,
                                       LastTm = item.Element("lastTm").Value,
                                       TrnstnId = Convert.ToInt32(item.Element("trnstnid").Value)
                                   };
                    StationCollection = new ObservableCollection<StationByRouteModel>(stations);

                    //정류소 목록 조회 화면으로 네비게이션
                    root.Navigate(new Uri("/Views/StationByRouteView.xaml", UriKind.Relative));
                    break;
            }

            if (1 == 1)
            {
            }
        }

        private ICommand getBusRouteListCommand;
        /// <summary>
        /// 노선 목록 조회 커맨드
        /// </summary>
        public ICommand GetBusRouteListCommand
        {
            get
            {
                if (getBusRouteListCommand == null)
                {
                    getBusRouteListCommand = new ActionCommand(() =>
                    {
                        if (SBusNum == null || SBusNum.Length <= 1)
                        {
                            MessageBox.Show("2글자 이상 입력해야 합니다.");
                            return;
                        }
                        //REST 형식 OpenAPI 호출
                        var uri = new Uri("http://ws.bus.go.kr/api/rest/busRouteInfo/getBusRouteList?ServiceKey=" + SKey.BusRouteInfo + "&strSrch=" + SBusNum);
                        //입력데이터 인코딩
                        SBusNum = Uri.EscapeUriString(SBusNum);
                        //비동기 호출, 호출 구분자로 GetBusRouteList를 사용함
                        wc.DownloadStringAsync(uri, "GetBusRouteList");
                    });
                }
                return getBusRouteListCommand;
            }
        }

        private ICommand selectionChangedCommand;
        /// <summary>
        /// 노선 목록에서 선택된 아이템이 변경된 경우 실행되는 커맨드
        /// </summary>
        public ICommand SelectionChangedCommand
        {
            get
            {
                if (selectionChangedCommand == null)
                {
                    selectionChangedCommand = new ActionCommand(item =>
                    {
                        //메인 프레임 입력 - 네비게이션하는데 필요
                        if (root == null)
                        {
                            //생성자에서는 이 데이터를 가지고 올 수가 없음..
                            root = App.Current.RootVisual as PhoneApplicationFrame;
                        }

                        //커맨드 파라메터로 전달 받은 오브젝트를 형변환
                        BusRouteModel route = item as BusRouteModel;
                        //형변환을 성공적으로 처리했다면
                        if (route != null)
                        {
                            //정류소 조회
                            var uri = new Uri("http://ws.bus.go.kr/api/rest/busRouteInfo/getStaionByRoute?ServiceKey=" + SKey.BusRouteInfo + "&busRouteId=" + route.BusRouteId);
                            wc.DownloadStringAsync(uri, "GetStaionByRoute");
                        }
                    });
                }
                return selectionChangedCommand;
            }
        }
    }
}

8. 이번 강좌는 여기서 마무리 하겠다.
윈도우 폰을 오늘 하얀색으로 예약을 했는데..언제 받을 수 있을지.. 받으면 이것 저것 할 일은 많은데..ㅎㅎ 그런데, 기분이 나쁜 점은 윈도우 폰을 팔기 시작 했으면서 어떻게 광고 한번 하는 걸 꼴을 못 봤다는 것이다. I랑 S팔때는 하루 종일 광고 하더니..윈도폰도 그정도 광고 했으면 잘 나갔을 것인데..쩝..
다시 한번 2012년은 윈도우폰이 뜨는 원년이 되었으면 한다.

'Windows Phone 8 > Korea Bus Information' 카테고리의 다른 글

My BusInfo app deploy  (0) 2012.01.08
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 5  (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
Posted by MVP kaki104

댓글을 달아 주세요