Subscribe RSS Join our Facebook Group Follow us on Twitter!
in Search

All about GIS

March 2011 - Posts

  • Bing Maps and OData (part 4)

    We meet again fellas. Postingan kali ini merupakan bagian keempat dari postingan saya tentang Bing Maps dan OData. Sebelumnya saya sudah menjelaskan tentang apa itu OData pada postingan pertama, lalu saya menjelaskan tentang pengambilan data dari OData pada postingan yang kedua, dan yang terakhir saya telah menjelaskan tentang MVVM dan MEF yang saya gunakan dalam aplikasi ini pada postingan yang ketiga. Nah, pada postingan yang keempat ini, kita akan mulai membuat behavior dan UI dari aplikasi. Ok, let’s get started…

    1. Creating ChildWindow Behavior

    Apa itu ChildWindow? ChildWindow merupakan sejenis pop-up window yang dapat kita munculkan untuk memberikan notifikasi kepada pengguna tentang sesuatu. Nah, ChildWindow ini akan saya gunakan untuk menampilkan detail dari Dinner yang kita pilih. Tambahkanlah sebuah class ke dalam project Anda dan beri nama sesuka Anda (dalam kasus saya, class ini saya beri nama ShowChildWindowAction.cs). Lalu, copy paste kode berikut ini ke dalam class tersebut.

       1: using System;
       2: using System.Windows;
       3: using System.Windows.Controls;
       4: using System.Windows.Interactivity;
       5:  
       6: namespace BingMapsOData
       7: {
       8:     [DefaultTrigger(typeof(UIElement), typeof(System.Windows.Interactivity.EventTrigger), new object[] { "MouseLeftButtonDown" })]
       9:     public class ShowChildWindowAction : TriggerAction<FrameworkElement>
      10:     {
      11:         public string ChildWindowType { get; set; }
      12:  
      13:         protected override void Invoke(object parameter)
      14:         {
      15:             ChildWindow window = Activator.CreateInstance(Type.GetType(ChildWindowType, false, true)) as ChildWindow;
      16:             if (window == null)
      17:             {
      18:                 return;
      19:             }
      20:             if (AssociatedObject != null)
      21:             {
      22:                 window.DataContext = AssociatedObject.DataContext;
      23:             }
      24:             window.Show();
      25:         }
      26:     }
      27: }

    Kode tersebut digunakan untuk memunculkan Child Window apabila terjadi sebuah event yang men-trigger-nya yang dalam hal ini adalah event MouseLeftButtonDown yang nantinya behavior tersebut akan kita taruh didalam pushpin.

    2. Creating Child Window

    Selanjutnya, kita akan membuat Child Window. Child Window ini akan muncul apabila pengguna mengklik salah satu pushpin yang ada pada Bing Map. Child Window ini berisi detail dari Dinner pada sebuah lokasi tertentu, sesuai dengan lokasi pushpin yang diklik oleh pengguna. Tambahkan Child Window pada project Anda dengan cara mengklik kanan pada project dan pilih Add > New Item.. atau tekan Ctrl+Shift+A lalu pilih Silverlight Child Window. Pada kasus saya, Child Window ini saya beri nama DetailsChildWindow.xaml.

    ChildWindow

    Kemudian, copy paste kode berikut..

    DetailsChildWindow.xaml

       1: <controls:ChildWindow x:Class="BingMapsOData.DetailsChildWindow"
       2:            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
       3:            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
       4:            xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
       5:            Title="{Binding Title, Mode=OneWay}">
       6:     
       7:     <controls:ChildWindow.Resources>
       8:         <Style x:Key="ChildWindowStyle" TargetType="controls:ChildWindow">
       9:             <Setter Property="IsTabStop" Value="false"/>
      10:             <Setter Property="TabNavigation" Value="Cycle"/>
      11:             <Setter Property="HorizontalAlignment" Value="Center"/>
      12:             <Setter Property="VerticalAlignment" Value="Center"/>
      13:             <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
      14:             <Setter Property="VerticalContentAlignment" Value="Stretch"/>
      15:             <Setter Property="BorderThickness" Value="1"/>
      16:             <Setter Property="BorderBrush">
      17:                 <Setter.Value>
      18:                     <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
      19:                         <GradientStop Color="#FFA3AEB9" Offset="0"/>
      20:                         <GradientStop Color="#FF8399A9" Offset="0.375"/>
      21:                         <GradientStop Color="#FF718597" Offset="0.375"/>
      22:                         <GradientStop Color="#FF617584" Offset="1"/>
      23:                     </LinearGradientBrush>
      24:                 </Setter.Value>
      25:             </Setter>
      26:             <Setter Property="OverlayBrush" Value="#7F000000"/>
      27:             <Setter Property="OverlayOpacity" Value="1"/>
      28:             <Setter Property="Template">
      29:                 <Setter.Value>
      30:                     <ControlTemplate TargetType="controls:ChildWindow">
      31:                         <Grid x:Name="Root">
      32:                             <VisualStateManager.VisualStateGroups>
      33:                                 <VisualStateGroup x:Name="WindowStates">
      34:                                     <VisualState x:Name="Open">
      35:                                         <Storyboard>
      36:                                             <DoubleAnimationUsingKeyFrames BeginTime="0" Storyboard.TargetName="Overlay" Storyboard.TargetProperty="Opacity">
      37:                                                 <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
      38:                                                 <EasingDoubleKeyFrame KeyTime="00:00:00.3" Value="1"/>
      39:                                             </DoubleAnimationUsingKeyFrames>
      40:                                             <DoubleAnimationUsingKeyFrames BeginTime="0" Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(RenderTransform).(Children)[0].ScaleX">
      41:                                                 <SplineDoubleKeyFrame KeyTime="0" Value="0"/>
      42:                                                 <SplineDoubleKeyFrame KeyTime="00:00:00.25" Value="0"/>
      43:                                                 <SplineDoubleKeyFrame KeyTime="00:00:00.4" Value="1"/>
      44:                                                 <SplineDoubleKeyFrame KeyTime="00:00:00.45" Value="1.05" KeySpline="0,0,0.5,1"/>
      45:                                                 <SplineDoubleKeyFrame KeyTime="00:00:00.55" Value="1"/>
      46:                                             </DoubleAnimationUsingKeyFrames>
      47:                                             <DoubleAnimationUsingKeyFrames BeginTime="0" Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(RenderTransform).(Children)[0].ScaleY">
      48:                                                 <SplineDoubleKeyFrame KeyTime="0" Value="0"/>
      49:                                                 <SplineDoubleKeyFrame KeyTime="00:00:00.25" Value="0"/>
      50:                                                 <SplineDoubleKeyFrame KeyTime="00:00:00.4" Value="1"/>
      51:                                                 <SplineDoubleKeyFrame KeyTime="00:00:00.45" Value="1.05" KeySpline="0,0,0.5,1"/>
      52:                                                 <SplineDoubleKeyFrame KeyTime="00:00:00.55" Value="1"/>
      53:                                             </DoubleAnimationUsingKeyFrames>
      54:                                         </Storyboard>
      55:                                     </VisualState>
      56:                                     <VisualState x:Name="Closed">
      57:                                         <Storyboard>
      58:                                             <DoubleAnimationUsingKeyFrames BeginTime="0" Storyboard.TargetName="Overlay" Storyboard.TargetProperty="Opacity">
      59:                                                 <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
      60:                                                 <EasingDoubleKeyFrame KeyTime="00:00:00.3" Value="0"/>
      61:                                             </DoubleAnimationUsingKeyFrames>
      62:                                             <DoubleAnimationUsingKeyFrames BeginTime="0" Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(RenderTransform).(Children)[0].ScaleX">
      63:                                                 <SplineDoubleKeyFrame KeyTime="00:00:00.2" Value="1"/>
      64:                                                 <SplineDoubleKeyFrame KeyTime="00:00:00.25" Value="1.05"/>
      65:                                                 <SplineDoubleKeyFrame KeyTime="00:00:00.45" Value="0"/>
      66:                                             </DoubleAnimationUsingKeyFrames>
      67:                                             <DoubleAnimationUsingKeyFrames BeginTime="0" Storyboard.TargetName="ContentRoot" Storyboard.TargetProperty="(RenderTransform).(Children)[0].ScaleY">
      68:                                                 <SplineDoubleKeyFrame KeyTime="00:00:00.2" Value="1"/>
      69:                                                 <SplineDoubleKeyFrame KeyTime="00:00:00.25" Value="1.05"/>
      70:                                                 <SplineDoubleKeyFrame KeyTime="00:00:00.45" Value="0"/>
      71:                                             </DoubleAnimationUsingKeyFrames>
      72:                                         </Storyboard>
      73:                                     </VisualState>
      74:                                 </VisualStateGroup>
      75:                             </VisualStateManager.VisualStateGroups>
      76:                             <Grid x:Name="Overlay" HorizontalAlignment="Stretch" Margin="0" VerticalAlignment="Top" Opacity="{TemplateBinding OverlayOpacity}" Background="{TemplateBinding OverlayBrush}"/>
      77:                             <Grid x:Name="ContentRoot" Height="{TemplateBinding Height}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}" Width="{TemplateBinding Width}" RenderTransformOrigin="0.5,0.5">
      78:                                 <Grid.RenderTransform>
      79:                                     <TransformGroup>
      80:                                         <ScaleTransform/>
      81:                                         <SkewTransform/>
      82:                                         <RotateTransform/>
      83:                                         <TranslateTransform/>
      84:                                     </TransformGroup>
      85:                                 </Grid.RenderTransform>
      86:                                 <Border HorizontalAlignment="Stretch" Margin="-1" VerticalAlignment="Stretch" Background="#14000000" BorderBrush="#14000000" BorderThickness="1" CornerRadius="2"/>
      87:                                 <Border HorizontalAlignment="Stretch" Margin="-2" VerticalAlignment="Stretch" Background="#0F000000" BorderBrush="#0F000000" BorderThickness="1" CornerRadius="2.25"/>
      88:                                 <Border HorizontalAlignment="Stretch" Margin="-3" VerticalAlignment="Stretch" Background="#0C000000" BorderBrush="#0C000000" BorderThickness="1" CornerRadius="2.5"/>
      89:                                 <Border HorizontalAlignment="Stretch" Margin="-4" VerticalAlignment="Stretch" Background="#0A000000" BorderBrush="#0A000000" BorderThickness="1" CornerRadius="2.75"/>
      90:                                 <Border Background="#FFFFFFFF" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2">
      91:                                     <Border Margin="1" CornerRadius="1.5">
      92:                                         <Border.Background>
      93:                                             <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
      94:                                                 <GradientStop Color="#FFE5E8EB" Offset="1"/>
      95:                                                 <GradientStop Color="#FFF6F8F9" Offset="0"/>
      96:                                             </LinearGradientBrush>
      97:                                         </Border.Background>
      98:                                         <Grid>
      99:                                             <Grid.RowDefinitions>
     100:                                                 <RowDefinition Height="Auto"/>
     101:                                                 <RowDefinition/>
     102:                                                 <RowDefinition Height="Auto"/>
     103:                                             </Grid.RowDefinitions>
     104:                                             <Border x:Name="Chrome" Width="Auto" BorderBrush="#FFFFFFFF" BorderThickness="0,0,0,1">
     105:                                                 <Border.Background>
     106:                                                     <LinearGradientBrush EndPoint="0.5,0.528" StartPoint="0.5,0">
     107:                                                         <GradientStop Color="#FFE5E8EB" Offset="1"/>
     108:                                                         <GradientStop Color="#FFFEFEFE" Offset="0"/>
     109:                                                     </LinearGradientBrush>
     110:                                                 </Border.Background>
     111:                                                 <Grid Height="Auto" Width="Auto">
     112:                                                     <Grid.ColumnDefinitions>
     113:                                                         <ColumnDefinition/>
     114:                                                         <ColumnDefinition Width="30"/>
     115:                                                     </Grid.ColumnDefinitions>
     116:                                                     <ContentControl HorizontalAlignment="Stretch" Margin="6" VerticalAlignment="Center" FontWeight="Bold" IsTabStop="False" Content="{TemplateBinding Title}"/>
     117:                                                 </Grid>
     118:                                             </Border>
     119:                                             <Border Margin="7" Grid.Row="1" Background="{TemplateBinding Background}">
     120:                                                 <ContentPresenter x:Name="ContentPresenter" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
     121:                                             </Border>
     122:                                             <Button x:Name="CloseButton" HorizontalAlignment="Right" VerticalAlignment="Center" IsTabStop="False" Grid.Column="1" Grid.Row="2" Content="Close" Padding="8,2" Margin="8"/>
     123:                                         </Grid>
     124:                                     </Border>
     125:                                 </Border>
     126:                             </Grid>
     127:                         </Grid>
     128:                     </ControlTemplate>
     129:                 </Setter.Value>
     130:             </Setter>
     131:         </Style>
     132:     </controls:ChildWindow.Resources>
     133:  
     134:     <controls:ChildWindow.Style>
     135:         <StaticResource ResourceKey="ChildWindowStyle"/>
     136:     </controls:ChildWindow.Style>
     137:     
     138:     <StackPanel x:Name="LayoutRoot" Background="WhiteSmoke" Width="210">
     139:         <TextBlock Text="RSVP " FontWeight="Bold"  Foreground="Gray" Padding="2" Margin="2" TextWrapping="Wrap"/>
     140:         <StackPanel Orientation="Horizontal">
     141:             <Button Margin="2" Padding="4" Name="btnTwitter" Click="btnTwitter_Click">
     142:                 <Image Source="Images/twitter.png" Width="16" Height="16"/>
     143:             </Button >
     144:             <Button Margin="2" Padding="4" Name="btnGoogle" Click="btnGoogle_Click">
     145:                 <Image Source="Images/google.png" Width="16" Height="16"/>
     146:             </Button>
     147:             <Button Margin="2" Padding="4" Name="btnYahoo" Click="btnYahoo_Click">
     148:                 <Image Source="Images/yahoo.png" Width="16" Height="16"/>
     149:             </Button>
     150:         </StackPanel>
     151:         <TextBlock Text="When? " FontWeight="Bold"  Foreground="Gray" Padding="2" Margin="2" TextWrapping="Wrap"/>
     152:         <TextBlock Text="{Binding Date}" Padding="2" Margin="2" TextWrapping="Wrap"/>
     153:         <TextBlock Text="Where? " FontWeight="Bold"  Foreground="Gray" Padding="2" Margin="2" TextWrapping="Wrap"/>
     154:         <TextBlock Text="{Binding Address}" Padding="2" Margin="2" TextWrapping="Wrap"/>
     155:         <TextBlock Text="Description " FontWeight="Bold"  Foreground="Gray" Padding="2" Margin="2" TextWrapping="Wrap"/>
     156:         <TextBlock Text="{Binding Description}" Padding="2" Margin="2" TextWrapping="Wrap"/>
     157:         <TextBlock Text="Hosted By: " FontWeight="Bold" Foreground="Gray" Padding="2" Margin="2" TextWrapping="Wrap"/>
     158:         <TextBlock Text="{Binding HostedBy}" Padding="2" Margin="2" TextWrapping="Wrap"/>
     159:         <TextBlock Text="Phone: " FontWeight="Bold"  Foreground="Gray" Padding="2" Margin="2" TextWrapping="Wrap"/>
     160:         <TextBlock Text="{Binding Phone}" Padding="2" Margin="2" TextWrapping="Wrap"/>
     161:         <TextBlock Text="Attendees: " FontWeight="Bold"  Foreground="Gray" Padding="2" Margin="2" TextWrapping="Wrap"/>
     162:         <TextBlock Text="{Binding Attendees}" Padding="2" Margin="2" TextWrapping="Wrap"/>
     163:     </StackPanel>
     164: </controls:ChildWindow>

    DetailsChildWindow.xaml.cs

       1: using System;
       2: using System.Windows;
       3: using System.Windows.Browser;
       4: using System.Windows.Controls;
       5: using BingMapsOData.ViewModels;
       6:  
       7: namespace BingMapsOData
       8: {
       9:     public partial class DetailsChildWindow : ChildWindow
      10:     {
      11:         public DetailsChildWindow()
      12:         {
      13:             InitializeComponent();
      14:         }
      15:  
      16:         private void btnTwitter_Click(object sender, RoutedEventArgs e)
      17:         {
      18:             var d = this.DataContext as DinnerViewModel;
      19:             HtmlPage.Window.Navigate(new Uri("http://nerddinner.com/RSVP/RsvpTwitterBegin/" + d.DinnerId), "_blank");
      20:         }
      21:  
      22:         private void btnGoogle_Click(object sender, RoutedEventArgs e)
      23:         {
      24:             var d = this.DataContext as DinnerViewModel;
      25:             HtmlPage.Window.Navigate(new Uri("http://nerddinner.com/RSVP/RsvpBegin/" + d.DinnerId + "?identifier=https%3A%2F%2Fwww.google.com%2Faccounts%2Fo8%2Fid"), "_blank");
      26:         }
      27:  
      28:         private void btnYahoo_Click(object sender, RoutedEventArgs e)
      29:         {
      30:             var d = this.DataContext as DinnerViewModel;
      31:             HtmlPage.Window.Navigate(new Uri("http://nerddinner.com/RSVP/RsvpBegin/" + d.DinnerId + "?identifier=https%3A%2F%2Fme.yahoo.com%2F"), "_blank");
      32:         }
      33:     }
      34: }
      35:  

    Oke, cukup sekian dulu nih. Masih ada pembahasan selanjutnya loh. Jadi, stay tuned ya..

    278 Views, 1 Comment(s), Published on: 03-31-2011 11:19 by veri to All about GIS
    | More
    Filed under: , , , , ,
  • Bing Maps and OData (part 3)

    Pada postingan pertama saya tentang Bing Maps dan OData, saya sudah menjelaskan secara garis besar tentang apa itu OData. Pada postingan yang kedua, saya sudah menjelaskan bagaimana membuat sebuah service untuk mengkonsumsi data dari OData. Nah, pada postingan saya yang ketiga ini, saya akan menjelaskan tentang pembuatan ViewModel dan MEF (Managed Extensibility Framework) yang saya gunakan dalam aplikasi ini.

    Model-View-ViewModel Design Pattern

    Model-View-ViewModel merupakan sebuah pola arsitektur yang digunakan dalam software engineering yang dibuat oleh Microsoft. Model MVVM ini sebenarnya berasal dari model MVC (Model-View-Controller), dimana MVVM lebih ditujukan untuk UI development platform yang modern seperti WPF (Windows Presentation Foundation) dan Silverlight.

    MVVM_Relation

    Bahasa gampangnya, MVVM ini digunakan untuk memfasilitasi para programmer dalam membangun logic dari sebuah aplikasi dan para designer dalam membuat UX agar mereka dapat bebas berkreasi tanpa harus saling bergantung antar satu sama lainnya.

    WLW-TheRevolutionHasBegun_10247-image_2

    Pada aplikasi ini, saya memiliki sebuah Model yaitu DinnerViewModel.cs dan sebuah ViewModel yaitu NerdDinnerViewModel.cs. Dalam DinnerViewModel.cs, terdapat objek-objek dari elemen Dinner seperti Title, Location, Address, dll. Sedangkan di dalam NerdDinnerViewModel.cs terdapat fungsi LINQ untuk mengquery Dinner yang didapatkan dengan memanfaatkan service yang telah kita buat pada postingan saya sebelumnya.

    Secara keseluruhan, DinnerViewModel.cs akan berisi kode-kode seperti berikut.

       1: using System;
       2: using BingMapsOData.NerdDinnerClient;
       3: using Microsoft.Maps.MapControl;
       4:  
       5: namespace BingMapsOData.ViewModels
       6: {
       7:     public class DinnerViewModel
       8:     {
       9:         public Location Location { get; set; }
      10:         public string Title { get; set; }
      11:         public string Description { get; set; }
      12:         public DateTime Date { get; set; }
      13:         public string Address { get; set; }
      14:         public string HostedBy { get; set; }
      15:         public int Attendees { get; set; }
      16:         public string Phone { get; set; }
      17:         public int DinnerId { get; set; }
      18:  
      19:         public DinnerViewModel(Dinner d)
      20:         {
      21:             Title = d.Title;
      22:             Location = new Location() { Latitude = d.Latitude, Longitude = d.Longitude };
      23:             Address = d.Address;
      24:             HostedBy = d.HostedBy;
      25:             Attendees = d.RSVPs.Count;
      26:             Description = d.Description;
      27:             Date = d.EventDate;
      28:             Phone = d.ContactPhone;
      29:             DinnerId = d.DinnerID;
      30:         }
      31:     }
      32: }

    Sedangkan dalam NerdDinnerViewModel.cs akan berisi kode-kode berikut.

       1: using System;
       2: using System.Collections.Generic;
       3: using System.ComponentModel.Composition;
       4: using System.Linq;
       5: using BingMapsOData.NerdDinnerClient;
       6: using BingMapsOData.Services.Data;
       7:  
       8: namespace BingMapsOData.ViewModels
       9: {
      10:     /// <summary>
      11:     /// View model for the nerd dinner
      12:     /// </summary>
      13:     public class NerdDinnerViewModel : ViewModelBase
      14:     {
      15:         #region Methods
      16:  
      17:         /// <summary>
      18:         /// Set the default values
      19:         /// </summary>
      20:         private void InitializeDefaults()
      21:         {
      22:             From = DateTime.Now.Subtract(new TimeSpan(12, 0, 0));
      23:             To = DateTime.Now.AddMonths(1);
      24:             OnPropertyChanged("From");
      25:             OnPropertyChanged("To");
      26:         }
      27:  
      28:         /// <summary>
      29:         /// Ctor
      30:         /// </summary>
      31:         public NerdDinnerViewModel()
      32:         {
      33:             CompositionInitializer.SatisfyImports(this);
      34:             InitializeDefaults();
      35:  
      36:             Service.DinnersChanged += (dinners) =>
      37:             {
      38:                 _dinners = dinners;
      39:                 Status = " | " + dinners.Count() + " Dinners from " + From.ToLongDateString() + " To " + To.ToLongDateString();
      40:                 OnPropertyChanged("Dinners");
      41:             };
      42:         }
      43:  
      44:         /// <summary>
      45:         /// Execute the service query to return the dinners
      46:         /// </summary>
      47:         public void QueryDinners()
      48:         {
      49:             Service.QueryDinners(From, To);
      50:             Status = " | Loading Dinners, Have a cup of tea..";
      51:         }
      52:  
      53:         #endregion
      54:  
      55:         #region Bindable Properties
      56:  
      57:         private IEnumerable<Dinner> _dinners = new List<Dinner>();
      58:  
      59:         private string _status = string.Empty;
      60:         public string Status
      61:         {
      62:             get
      63:             {
      64:                 return _status;
      65:             }
      66:             set
      67:             {
      68:                 _status = value;
      69:                 OnPropertyChanged("Status");
      70:             }
      71:         }
      72:  
      73:         public IEnumerable<DinnerViewModel> Dinners
      74:         {
      75:             get
      76:             {
      77:                 var items = from d in _dinners
      78:                             select new DinnerViewModel(d);
      79:                 return items;
      80:             }
      81:         }
      82:  
      83:         public DateTime From { get; set; }
      84:         public DateTime To { get; set; }
      85:  
      86:         #endregion
      87:  
      88:         #region Imported Services
      89:  
      90:         [Import(typeof(INerdDinnerService))]
      91:         public INerdDinnerService Service { get; set; }
      92:  
      93:         #endregion
      94:     }
      95: }

    Mungkin sekarang timbul pertanyaan. Pada part 2, terdapat [Export(typeof(INerdDinnerService))] lalu pada postingan kali ini terdapat [Import(typeof(INerdDinnerService))]. Sebenarnya itu buat apaan sih? Oke, sekarang juga akan saya jelaskan.

    Managed Extensibility Framework

    Managed Extensibility Framework atau MEF merupakan sebuah library untuk membuat sebuah aplikasi yang ringan dan extensible. MEF memungkinkan para developer untuk membuat extension-extension dari aplikasi tanpa konfigurasi apapun. Selain itu, dengan menggunakan MEF, extension-extension tersebut tidak hanya bisa di re-use dalam sebuah aplikasi tetapi juga dapat digunakan dalam aplikasi lain. MEF ini sudah include di dalam .NET Framework 4 dan Silverlight 4.

    MEF_Diagram

    Untuk lebih jelasnya tentang pemrograman menggunakan MEF, bisa dilihat disini.

    Oke, kayaknya cukup sampai sini dulu deh. Silakan di pelajari sedikit demi sedikit. Tunggu pembahasan selanjutnya ya…

    436 Views, 3 Comment(s), Published on: 03-07-2011 21:51 by veri to All about GIS
    | More
    Filed under: , , , ,
  • Bing Maps and OData (Part 2)

    Pada postingan saya sebelumnya, saya sudah sedikit menjelaskan tentang apa itu OData. Nah, pada postingan ini dan seterusnya, saya akan menjelaskan tentang cara membuat sebuah aplikasi Bing Maps sederhana yang memanfaatkan OData. Sebelum melanjutkan, kalian harus memiliki beberapa tools berikut:

    Setelah kalian sudah menginstal semua tools tersebut, sekarang saatnya kita mulai membuat aplikasinya.

    1. Buat sebuah aplikasi Silverlight baru.

    Buat sebuah aplikasi Silverlight baru pada Visual Studio dan tambahkan reference-reference seperti pada gambar berikut.

    References

    2. Mengkonsumsi OData di Silverlight

    Untuk mengkonsumsi OData di Silverlight, kalian cukup menambahkan service reference ke service OData. Caranya, klik kanan pada Silverlight project kalian dan pilih Add Service Reference. Tambahkan service reference ke endpoint OData Nerd Dinner.

    OData Service

    3. Mengambil Data

    Langkah selanjutnya adalah mengambil data dari OData endpoint. Buatlah sebuah interface bernama INerdDinnerService.cs dan sebuah kelas NerdDinnerService.cs yang mengimplementasi interface tersebut. Di dalam kelas NerdDinnerService.cs, kita akan membuat sebuah menambahkan filter untuk mengquery data diantara dua buah tanggal.

    Apakah hal tersebut bisa dilakukan? Bisa, karena OData mendukung berbagai URI convention dan bentuk-bentuk query. Sebagai contoh, misalnya kita ingin mengambil 5 dinner teratas, kita bisa menambahkan $top=5 pada URI sehingga bentuk URI-nya akan menjadi seperti ini http://nerddinner.com/Services/OData.svc/Dinners?$top=5.

    Pada kasus kali ini, saya akan meminta data dinner yang berada pada range tanggal tertentu. Berdasarkan URI convention dari OData, maka bentuk query yang akan kita buat kurang lebih berbentuk seperti ini http://nerddinner.com/Services/OData.svc/Dinners?$filter=EventDate%20le%20datetime'2011-04-01T09:00:00'%20and%20EventDate%20gt%20datetime'2011-03-01T09:00:00'

    Interface INerdDinnerService.cs akan berisi kode berikut:

       1: using System;
       2: using System.Collections.Generic;
       3: using BingMapsOData.NerdDinnerClient;
       4:  
       5: namespace BingMapsOData.Services.Data
       6: {
       7:     /// <summary>
       8:     /// INerdDinnerService interface
       9:     /// </summary>
      10:     public interface INerdDinnerService
      11:     {
      12:         void QueryDinners(DateTime from, DateTime to);
      13:         event Action<IEnumerable<Dinner>> DinnersChanged;
      14:     }
      15: }

    Sedangkan untuk kelas NerdDinnerService.cs-nya akan berbentuk seperti ini:

       1: using System;
       2: using System.Collections.Generic;
       3: using System.Collections.ObjectModel;
       4: using System.ComponentModel.Composition;
       5: using System.Data.Services.Client;
       6: using System.Windows;
       7: using BingMapsOData.NerdDinnerClient;
       8:  
       9: namespace BingMapsOData.Services.Data
      10: {
      11:     [Export(typeof(INerdDinnerService))]
      12:     public class NerdDinnerService : INerdDinnerService
      13:     {
      14:         ObservableCollection<Dinner> _dinners;
      15:  
      16:         /// <summary>
      17:         /// Query the dinners in nerd dinner database
      18:         /// </summary>
      19:         public void QueryDinners(DateTime from, DateTime to)
      20:         {
      21:             // Create a new data service context.
      22:             var context = new NerdDinnerEntities
      23:               (new Uri("http://nerddinner.com/Services/OData.svc/", UriKind.Absolute));
      24:  
      25:             // Creates the query. Dirty strings for now
      26:             string exp = "EventDate le " + GetODataFormat(to) + " and EventDate gt " + GetODataFormat(from);
      27:  
      28:             //Add a filtering option
      29:             DataServiceQuery<Dinner> query = context.Dinners.AddQueryOption("$filter", exp).Expand("RSVPs");
      30:  
      31:             try
      32:             {
      33:                 // Begin the query execution.
      34:                 query.BeginExecute(OnDinnerQueryComplete, query);
      35:             }
      36:             catch (Exception ex)
      37:             {
      38:                 MessageBox.Show(ex.Message);
      39:             }
      40:         }
      41:  
      42:         /// <summary>
      43:         /// Gets the oDataFormat
      44:         /// </summary>
      45:         public string GetODataFormat(DateTime dt)
      46:         {
      47:             return "datetime'" + dt.ToString("yyyy-MM-ddThh:mm:ss") + "'";
      48:         }
      49:  
      50:         /// <summary>
      51:         /// Will be invoked upon completion of the query
      52:         /// </summary>
      53:         /// <param name="result"></param>
      54:         private void OnDinnerQueryComplete(IAsyncResult result)
      55:         {
      56:             // Get the original query back from the result.
      57:             DataServiceQuery<Dinner> query = result.AsyncState as DataServiceQuery<Dinner>;
      58:  
      59:             try
      60:             {
      61:                 _dinners = new DataServiceCollection<Dinner>(query.EndExecute(result));
      62:                 if (DinnersChanged != null)
      63:                     DinnersChanged(_dinners);
      64:             }
      65:             catch (DataServiceQueryException ex)
      66:             {
      67:                 MessageBox.Show(ex.Message);
      68:             }
      69:         }
      70:  
      71:         /// <summary>
      72:         /// Event to raise when dinners changed
      73:         /// </summary>
      74:         public event Action<IEnumerable<Dinner>> DinnersChanged;
      75:     }
      76: }

    Fungsi dari QueryDinners adalah untuk memfilter dinner yang berada dalam selang waktu tertentu. Saat kita melakukan BeginExecute, kita melempar callback OnDinnerQueryComplete agar nantinya callback ini dipanggil setelah eksekusi query selesai. Di dalam OnDinnerQueryComplete ini kita memanggil EndExecute untuk menampilkan hasil dari query. Selain itu, kita juga memanggil event DinnersChanged untuk memberikan notifikasi pada ViewModel kita.

    Mudah bukan?

    Untuk postingan kali ini mungkin cukup sampai disini dulu. Sampai jumpa di postingan saya selanjutnya…

    569 Views, 4 Comment(s), Published on: 03-02-2011 4:34 by veri to All about GIS
    | More
    Filed under: , , , ,