티스토리 뷰

반응형

1. 만들기 시작~
File -> New Project -> Silverlight for Windows Phone -> Windows Phone Application
Name : BusInfo
Target Windows Phone OS Version : Windows Phone OS 7.1

초기화면이 출력되면 바로 실행해본다(Ctrl + F5) 윈도우 폰 에물레이터가 실행되고 응용프로그램이 배포되어서 실행된다.

MY APPLICATION을 원하는 이름으로 바꾼다.
page name : 버스 목록 조회로 변경
글씨가 너무 커서 '회'자가 짤리니.. FontSize를 변경해준다. -> 64
다시 실행해서 확인 한다.


2. 버스 목록 조회하기
노선번호 목록 조회
http://api.bus.go.kr/contents/sub02/getBusRouteList.html
위의 서비스를 이용해서 조회를 해야한다. 여기서 인증키가 꼭 필요한데.. 인증키는 강좌 1번을 참고 하기 바란다.


3. 필요한 폴더 생성
BusInfo 프로젝트 선택 -> 마우스 오른쪽 클릭 -> Add -> New Folder
Converters, Functions, Icons, Models, ViewModels, Views
6개의 폴더를 생성해 놓는다.

4. MainPage.xaml에 컨트롤을 배열해보자
xaml 파일에 디자인을 할때, 바인딩을 할때는 블랜드를 이용한다.(VS2010에서 프로젝트를 열어 놓은 상태로 작업한다)
Microsoft Expression Blend 4 실행 -> File -> Open Project/Solution -> BusInfo.sln 선택 Open


5. 구역 나누기
Objects and Timeline -> ContentPanel 선택
MainPage.xaml에 마우스를 가져다가 대면 노란색 라인이 보인다.

위의 위치에서 클릭하면 구역이 하나 만들어진다. 소스를 확인해보자

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
 <Grid.RowDefinitions>
 <RowDefinition Height="0.081*"/> <!--1번구역-->
 <RowDefinition Height="0.919*"/> <!--2번구역-->
 </Grid.RowDefinitions>
</Grid>


나누어진 1번 구역에는
노선번호 _____________ [조회] 이런 내용을 올려 놓을 것이다.
1번 구역은 높이가 변경될 필요가 없으니 높이를 고정 시키자


<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
 <Grid.RowDefinitions>
 <RowDefinition Height="72"/>
 <RowDefinition/>
 </Grid.RowDefinitions>
</Grid>

 

노선번호 -> TextBlock
_________ -> TextBox
[조회] -> Button
3개의 컨트롤을 1번 구역에 올려 놓아야하는데 2가지 방식중에 하나를 선택 할 수 있다.
가) 1번구역에 Grid를 올려 놓고 컬럼을 만들어서 사용하는 방법
나) 1번구역에 StackPanel을 올려 놓고 Orientation을 Horizontal로 만들어서 사용하는 방법
여기서는 나)의 방법을 사용해서 배치를 한다.(편해서..)


<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="TextBox" Width="275"/>
  <Button Content="조회"/>
 </StackPanel>
</Grid>

이정도면 1구역에서 해야할 일은 다 한 것 같다. 다음 2구역으로 넘어가보자
2구역에는 ListBox컨트롤 하나만 올려 놓으면 된다.

<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="TextBox" Width="275"/>
  <Button Content="조회"/>
 </StackPanel>
 <ListBox Grid.Row="1"/>
</Grid>


화면상으로 올려 놓은 것인지 아닌지 확실히 보이지는 안치만..올라가있는 것이다.
화면 디자인은 1차 완료~ 저장 하고 VS2010으로 돌아가서 실행해보자. 이때 VS2010에 xaml이 열려있다면..
외부에서 파일이 변경되어서 다시 불러들여야 한다는 메시지가 출력된다. 그렇게 하라구 해준다.
그리고, 다시 실행 해 주면 방금 수정된 내용이 화면에 출력된다.


6. MainPageViewModel.cs 만들기
조회버튼의 클릭 이벤트를 강제로 만들어서 사용할 수도 있지만..여기서는 MVVM 패턴을 적용해서 프로그램을 하기 때문에..
ViewModel을 만들어 주어야 한다. (MVVM 패턴을 사용하지 않으면 바인딩 기능을 이용할 수 없다..그러므로 꼭 사용하도록 하자)

우린 다시 VS2010으로 돌아와서
ViewModels폴더를 선택하고 Add -> Class -> name : MainPageViewModel.cs 파일을 추가하자

ViewModel의 중요기능 중에 프로퍼티 체인지 이벤트가 있다. 이 것을 사용 하기 위해서는 INotifyPropertyChanged 을 상속 받아야 한다. 상속 받은 후 구현을 하면 아래와 같은 소스가 만들어진다.

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel;

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

    }
}

프로퍼티 체인지 이벤트를 구현하는 것은 바인딩을 원하는 모든 클래스에서 이루어져야 한다. 그렇치 않으면 데이터가 변경이 되더라도 화면에 그 내용이 표시 되지 않는 사태가 발생하기 때문이다.

7. MainPageViewModel.cs 다시 작업

뷰 모델의 기본적인 구성을 살펴 보면
가) 프로퍼티 체인지 이벤트 구현
나) 조회 조건 프로퍼티
다) 뷰모델에서 사용할 프로퍼티 or 변수
-> 뷰와 바인딩을 해야하는 넘들은 프로퍼티로, 아니면 일반 변수로 만들어도 됨
-> 구분하기 귀찮으면 모두 프로퍼티로 만들어두 문제는 없음
-> 프로퍼티도 바인딩 된 후에 변경되었을 때 화면에 바로 반영해 주어야하는 경우에는 FirePropertyChange를 사용해야하고, 그냥 바인딩만 할려고 하면 프로퍼티로만 만들어 놓으면 된다.
라) 생성자
마) 뷰모델 프로퍼티 체인지 이벤트 구현
바) 커맨드 구현
위의 구성은 내 나름대로 정의를 한 것으로 프로그램 하는데 참고 사항으로 사용하면 될 것이다.

** 조회 조건 추가 - 일반 프로퍼티
/// <summary>
/// 검색할 버스 노선 번호
/// </summary>
public string SBusNum { get; set; }

//웹클라이언트
WebClient wc;

음..다음에 인증키를 넣어야하는데..인증키는 따로 모델을 만들어서 사용하기로 하자.

8. ServiceKey.cs 작업
Models폴더를 선택하고 -> Add -> Class -> name : ServiceKey.cs 추가

using System;

namespace BusInfo.Models
{
    public class ServiceKey
    {
        /// <summary>
        /// 버스정보용 인증키
        /// </summary>
        public string BusRouteInfo { get; private set; }

        public ServiceKey()
        {
            string tempKey;
            //버스루트정보용 키
            tempKey = string.Format("여기에 본인이 받은 인증키를 넣는다.");
            //URL인코딩 작업을 해서 넣어 두어야함
            BusRouteInfo = Uri.EscapeUriString(tempKey);
        }
    }
}

본인이 받은 인증키를 " 여기에 본인이 받은 인증키를 넣는다." 여기에 입력한다.
중요한 부분은 인증키 자체를 Encoding을 해주어야 한다는 부분이다.

그리고, 다시 MainPageViewModel.cs로 이동해서 인증키 클래스를 추가한다.

9. MainPageViewModel.cs 다시 빽

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

자 이제 목표는 일단 호출을 날리고 결과가 들어오는 것을 확인하는 것이다.
그럼, 기본 생성자에서 wc와 SKey를 생성하고, wc.DownloadStringCompleted 이벤트도 구현하고, 마지막으로 DLL도 하나 추가한다.
References 선택 -> Add Reference -> System.Xml.Linq 추가    //XElement 사용하기 위해

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

/// <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);

}

여기까지 하면 wc를 이용해서 요청을 날리면 결과를 xml이란 곳에서 확인이 가능하다.
그럼 요청을 날려보자
F6키를 눌러서 빌드를 해보자 에러가 없으면 다음으로 이동~


10. 사용자 인터렉션(User Interactions) 처리
ViewModel에서는 ICommand를 하나 만들고, View에서는 InvokeCommandAction을 이용해서 ViewModel에 있는 명령을 실행하게 된다. 처음으로 조회를 할 서비스에 대해서 알아보자
노선번호 목록 조회
http://api.bus.go.kr/contents/sub02/getBusRouteList.html
2개의 요청 변수를 가지는 것을 확인 할 수 있는데, 한 개는 인증키고, 또 하나는 검색할 노선 번호이다.

다시 하나의 DLL을 추가해보자
Add Reference -> Microsoft.Expression.Interactions
위의 DLL은 ActionCommand를 사용하기위해 필요하다. 커맨드를 추가한다.

private ICommand getBusRouteListCommand;
/// <summary>
/// 노선 목록 조회 커맨드
/// </summary>
public ICommand GetBusRouteListCommand
{
    get
    {
        if (getBusRouteListCommand == null)
        {
            getBusRouteListCommand = new ActionCommand(() =>
            {
                if (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;
    }
}

F6을 눌러서 빌드를 해준다.(빌드 작업을 해줘야 블랜드에서 인식이 가능하다.)
여기까지 작업이 완료되었으면 이제 다시 블랜드로 넘어가서 뷰와 뷰모델과 연결하는 작업을 해주도록 하자.

11. 뷰와 뷰모델 연결하기


Objects and Timeline에서 PhoneApplicationPage를 선택한다.-> 화면 오른쪽 하단에 있는 Common Properties -> DataContext -> New 클릭


MainPageViewModel을 선택하고 OK를 누른다.

위의 작업은 뷰에 뷰모델을 DataContext에 붙이는 작업이다. 이렇게 DataContext에 뷰모델을 넣어 주어야 블랜드에서 뷰모델의 프로퍼티와 커맨드를 바인딩 할 수 있다.

화면에 ㅡ 모양을 클릭해서 화면과 소스를 동시에 보는 mode로 변경한다.
소스에서 방금 추가된 부분을 찾아간다.


뷰에서 뷰모델을 붙여 놓으면 디자인 타임에서도 생성을 시켜서 작업을 할 수 있다. 하지만, 여기서는 뷰에서 뷰모델을 인스턴스 시키지 않을 것이다. 그래서 이 부분에 있는 소스에서 phone:PhoneApplicationPage. 부분을 d:로 변경한다. d:는 디자인 타임에서만 사용하는 넘이란 뜻이다.

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

이렇게 변경하면 디자인 타임 때는 바인딩이나 모든 것이 가능하지만, 런타임 때에는 아무런 동작을 하지 않는다.

12. TextBox와 뷰모델의 프로퍼티를 바인딩하기
확인을 위해서 TextBox를 클릭하고 Text 프로퍼티를 찾아보자..그곳에 TextBox라는 글씨가 있고 오른쪽에 하얀색 네모박스가 있는데 그 박스를 클릭하면
팝업 메뉴가 나온다. 메뉴에서 Data Binding을 선택한다.


Data Context란 이름에 뷰모델의 프로퍼티와 커맨드가 보이게 된다. 여기서 우리는 텍스트박스와 SBusNum이란 뷰모델의 프로퍼티를 TwoWay로 바인딩을 할 수 있다.

* Binding은 거의 2가지를 사용하는데
OneWay는 뷰에서 데이터를 변경할 필요가 없는 읽기 전용으로 사용할 경우이고,
TwoWay는 뷰에서 데이터를 변경해야 하는 경우에 사용하면 된다.

우리는 뷰에서 버스 번호를 입력 해서 프로퍼티를 변경해야 하기 때문에 TwoWay로 바인딩을 해준다.
OK눌러서 바인딩을 완료 한다.
그러면 Text 프로퍼티가 노란색 띠를 가지도록 변경되고, 오른쪽에 하얀 네모 박스도 동일하게 변경된다.
이렇게하면 뷰에있는 텍스트 박스와 뷰모델에 있는 프로퍼티의 바인딩이 성공적으로 완료가 된 것이다.

13. InvokeCommandAction 연결하기


Assets텝 선택 -> Behaviors 선택 -> InvokeCommandAction을 선택
선택한 내용을 드래그 해서 Button까지 끌어다가 놓으면 Button에 InvokeCommandAction이 추가된다.


위와 같은 화면이 나오면 된다.
추가된 커맨드 엑션에 세부적인 설정을 해준다. 오른쪽 상단에 Command 프로퍼티 오른쪽에 디스크 모양 아이콘을 클릭한다


그러면 Create Data Binding 팝업이 출력되면서 커맨드를 선택할 수 있다. 여기서 방금 만들어 놓았던 GetBusRouteListCommand를 선택하고 OK를 클릭한다.
이제 조회 버튼과 뷰모델에 있는 GetBusRouteListCommand는 바인딩 되었다.

<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"/>
          <Button Content="조회">
           <i:Interaction.Triggers>
            <i:EventTrigger EventName="Click">
             <i:InvokeCommandAction Command="{Binding GetBusRouteListCommand, Mode=OneWay}"/>
            </i:EventTrigger>
           </i:Interaction.Triggers>
          </Button>
         </StackPanel>
         <ListBox Grid.Row="1"/>
        </Grid>
    </Grid>

</phone:PhoneApplicationPage>

조회 기능까지 추가한 뷰의 소스이다.

14. MainPage.xaml.cs에서 마무리 작업 하기
다시 VS2010으로 돌아오고, 실행해 보자.
오류도 없고 화면도 출력된다. 그런데 조회 버튼을 클릭해도 아무런 반응이 없다. 커맨드가 실행이 되는지 확인 해볼려면
...
getBusRouteListCommand = new ActionCommand(() =>
  { //요기에 브레이크를 걸어 놓는다.
      if (SBusNum.Length <= 1)
...
브레이크를 걸고 실행해도 아무런 반응이 없을 것이다. 좀 전에 이야기를 했듯이..우린 DataContext라는 곳에 뷰모델을 연결해 놓았지만..그건 디자인 타임에서만 적용되기 때문이다.
그래서 런타임에서 뷰모델을 뷰의 DataContext에 넣어주는 코딩을 MainPage.xaml.cs에 추가하도록 하자


using System.ComponentModel;
using BusInfo.ViewModels;
using Microsoft.Phone.Controls;

namespace BusInfo
{
    public partial class MainPage : PhoneApplicationPage
    {
        /// <summary>
        /// 뷰모델
        /// </summary>
        public MainPageViewModel ViewModel { get; set; }

        // Constructor
        public MainPage()
        {
            InitializeComponent();

            //디자인 타임이 아닌 경우 실행
            if (!DesignerProperties.IsInDesignTool)
            {
                //뷰모델 인스턴스
                ViewModel = new MainPageViewModel();
                //DataContext에 입력
                this.DataContext = ViewModel;
            }
        }
    }
}

** 뷰모델을 왜 이렇게 만들어서 붙일까??
처음에 그냥 뷰모델을 블랜드에서 만들고 그대로 사용해도 사실 문제는 없다. 다만, 이 프로그램에서는 뷰모델을 다른 뷰에서도 사용하기 위해서 위와 같은 방법을 사용한 것이다.
원래 원했던 내용은 MEF를 사용해서 깔끔하게 같이 사용하고 싶었는데 불행하게도 WP에서는 MEF를 지원하지 않는다..그래서 약간 다른 방법으로 처리를 했고, 더 자세한 사항은 다음 화면을 추가했을 때 자세하게 알아 보도록 하자

다시 실행하고, 조회 노선 번호를 입력 한 후에 조회 버튼을 클릭해 보자.
이제 브레이크가 걸리면 작업이 성공적인 것이다. 안 된다면..다시 찬찬히 따라 해 보도록 한다.

OpenAPI 조회 명령이 성공적으로 완료가 되면 wc_DownloadStringCompleted를 타게 되고, 어떤 결과가 리턴 되는지를 확인 한 후에 Model을 만들도록 한다.

15. MainPageViewModel.cs

/// <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)  //여기에 브레이크
    {
    }
}

브레이크가 걸린곳에서 xml에 어떤 내용이 들어오는지 확인 해보면

<ServiceResult>
  <comMsgHeader />
  <msgHeader>
    <headerCd>0</headerCd>
    <headerMsg>정상적으로 처리되었습니다.</headerMsg>
    <itemCount>5</itemCount>
  </msgHeader>
  <msgBody>
    <itemList>
      <busRouteId>90000062</busRouteId>
      <busRouteNm>3100안산</busRouteNm>
      <edStationNm>강남역</edStationNm>
      <routeType>8</routeType>
      <stStationNm>신안산대학교</stStationNm>
      <term>60</term>
    </itemList>
    <itemList>
      <busRouteId>90000134</busRouteId>
      <busRouteNm>3100의정부</busRouteNm>
      <edStationNm>양재역</edStationNm>
      <routeType>8</routeType>
      <stStationNm>대진대.학생회관</stStationNm>
      <term>30</term>
    </itemList>
    <itemList>
      <busRouteId>90000326</busRouteId>
      <busRouteNm>31파주</busRouteNm>
      <edStationNm>불광동시외버스터미널</edStationNm>
      <routeType>8</routeType>
      <stStationNm>갈곡리(회차지점)</stStationNm>
      <term>25</term>
    </itemList>
    <itemList>
      <busRouteId>90000352</busRouteId>
      <busRouteNm>3100김포</busRouteNm>
      <edStationNm>신촌역2호선</edStationNm>
      <routeType>8</routeType>
      <stStationNm>화도터미널</stStationNm>
      <term>60</term>
    </itemList>
    <itemList>
      <busRouteId>90000176</busRouteId>
      <busRouteNm>3101안산</busRouteNm>
      <edStationNm>강남역</edStationNm>
      <routeType>8</routeType>
      <stStationNm>신안산대학교</stStationNm>
      <term>80</term>
    </itemList>
  </msgBody>
</ServiceResult>

이런 결과가 리턴 된 것을 알 수 있다.
그럼 위의 결과를 기준으로  Models 폴더에 BusRouteModel.cs라는 모델을 만들어 보기 바란다.


MainPageViewModel.cs 최종소스

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel;
using BusInfo.Models;
using System.Xml.Linq;
using Microsoft.Expression.Interactivity.Core;


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;

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

        /// <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)
            {
            }
        }

        private ICommand getBusRouteListCommand;
        /// <summary>
        /// 노선 목록 조회 커맨드
        /// </summary>
        public ICommand GetBusRouteListCommand
        {
            get
            {
                if (getBusRouteListCommand == null)
                {
                    getBusRouteListCommand = new ActionCommand(() =>
                    {
                        if (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;
            }
        }

    }
}

16. 이번회의 강좌는 여기까지만 하도록 하겠다.

조회를 날리고 결과를 가지고 왔으니 이제 그 결과를 가공해서 화면에 출력하는 일만 남은 것 같다.
쓰고 보니 스크롤의 압박이 상당히 심할 것 같은데..중간에 끊을 수가 없었다는 것을 알아 주기를 바란다.이 글이 윈폰 엡 개발하는데 만은 도움이 되었으면 좋겠고..리플도 만이 남겨주면 좋겠다.

 

Windows Phone 7 Mango 버스 정보 검색 App 만들기 3

반응형

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

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 2  (0) 2012.01.04
Seoul Bus Info Search App Dev 1  (0) 2012.01.04
댓글