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

All about GIS

  • Reactive Extensions (Rx)

    Hello readers, we meet again. In this blog post, I will help you in understanding Reactive Extensions (Rx).

    Reactive Extensions (Rx)

    According to MSDN Library,

    Reactive Extensions is a library for composing asynchronous and event-based programs using observable sequences and LINQ-style query operators.

    Rx represents many data sequences, such as stream of data, web services requests, system notifications, or a series of user input, as observable sequences. If subscribed by an application, this observable sequences can push data to the application asynchronously as new data arrive.

    The Rx library is available for desktop application development using .NET, and also available for Silverlight, Windows Phone 7, and JavaScript. The differences between all of them can be read in here.

    Interactive V.S Reactive Programming

    At this point, maybe you’ll ask me, what is interactive programming? And what is reactive programming? What’re the differences between them and how do they related to Rx?

    In interactive programming, the application will try to “pull” the data from the data source to get more information. In code, it is represented by the IEnumerable<T>/IEnumerator<T> interface. The IEnumerable<T> interface have a GetEnumerator() method to iterate through the collection while the IEnumerator<T> interface have the MoveNext method to advances the enumerator to the next element of the collection if there is any.

    In reactive programming, the application don’t have to “pull” the data from the data source. Instead, the data source will “push” the data to the application if there are more data to offer. This is what they call with Rx. This action can be done by subscribing to the IObservable<T>/IObserver<T> interface. The IObservable<T> interface is similar to IEnumerable<T> interface. It abstracts a sequence of data, and keeps a list of IObsever<T> implementations that are interested in the data sequence.

    For more tutorial about Rx, you can visit this link.

    That’s all for this post. See you soon in my next post and ciao…

    382 Views, 0 Comment(s), Published on: 08-14-2011 7:44 by veri to All about GIS
    | More
    Filed under: ,
  • Creating an ADO.NET Data Service

    In my previous blog posts, I have wrote about how to consume an Open Data Protocol (OData) feed. In those posts, I used the NerdDinner OData end point. Right now, maybe a few of you are wondering, how can I make that OData service in .NET? Well, it’s actually not as hard as you thought it would be and I’m going to explain it how. Oh I almost forgot, in this example, I will use the Northwind sampe database which can be downloaded in here.

    1. Create a new WCF Service application

    New WCF Service Application

    If you look at the solution explorer, you will see that we have IService1.cs and Service1.svc. Just delete these two files. We don’t need them anyway.

    Service

    2. Define the data model

    To define the data model, I’m going to use Entity Framework. Maybe you are going to ask me, why am I using the Entity Framework? Well, it’s simply because Entity Framework make this task a whole lot easier so we can save time. To create an Entity Framework, you need to add a new ADO.NET Entity Data Model. I will name it Northwind.edmx because I’m using the Northwind database.

    ADO.NET Entity Data Model

    In the Entity Data Model Wizard, select Generate from Database.

    Entity Data Model Wizard

    Then choose your connection and create the connection string.

    Data Connection

    Pick the tables that you want to publish and click Finish.

    Database Objects

    3. Create the data service

    OK, we already have the data model so it’s time to create the data service. We need to add a new WCF Data Service to our project.

    WCF Data Service

    After the WCF Data Service have been created, you need to change the /* TODO: put your data source class name here */ with the name of the entity container of the data model, which in my case is NorthwindEntities.

    4. Enabling access to data service resources

    Put the code below to the InitializeService function in Northwind.svc.cs file.

    config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);

    And that’s it. You can now run the application. But before you do, maybe you need to turn off the feed reading view in Internet Explorer which is located in Internet Options->Content and choose Settings in the Feed and Web Slices then uncheck the Turn on feed reading view. After you run the application, it will appear something like this:

    Result

    Just test that out with the OData query in here. Enjoy…

    457 Views, 0 Comment(s), Published on: 07-04-2011 20:15 by veri to All about GIS
    | More
  • BINER (Bakti Informatika untuk Negeri) @ SMPN 22 Bandung

    A few weeks ago, I delivered a speech about Rich Internet Application at SMPN 22 Bandung as part of the BINER program hosted by HMIF (Himpunan Mahasiswa Informatika) ITB. There were only 10 students that attended the presentation but they were all really enthusiastic about this topic. I’m really happy to see these middle school students that love to learn something beyond their own school curriculum.

    2011-05-23 15.01.492011-05-23 15.02.062011-05-23 15.03.042011-05-23 15.06.00

    402 Views, 0 Comment(s), Published on: 06-06-2011 11:47 by veri to All about GIS
    | More
    Filed under:
  • MSDN Indonesia Windows Phone 7 Challenge Winner Announced

    The announcement has been made last Friday and I won the Windows Phone 7 Challenge held by Microsoft Indonesia in application category. I created a news reader application that can read news from detik, okezone, kompas, and metrotvnews. The idea of this application came from my daily activities. Usually, I start my day with reading news from those sites. But sometimes I realize, it’s a bit troublesome if you have to switch to one site then go to the other. It will be great to have an application that can combine all the news from every site. That simple thought became an idea to create this news reader application.

    The official announcement was made on MSDN Indonesia website in here. The showcase of the application that I have made on YouTube can be seen here. Well, as the winner, I will be rewarded with a Windows Phone device (but I don’t know which one) and my application will be uploaded to the Windows Phone Marketplace. I haven’t been contacted by Microsoft Indonesia for further information because it’s weekend. So, I will announce it on my website if this application ready to download in marketplace. Cheers…

    397 Views, 0 Comment(s), Published on: 05-31-2011 20:30 by veri to All about GIS
    | More
    Filed under:
  • Bing Maps Locator Wizard by InKnowledge

    Last week, InKnowledge just released the Bing Maps Locator Wizard, a tool that allows corporations and general public to get their location data on a Bing Maps map in minutes. The wizard walks users through the simple steps required to create and customize a locator application which can be downloaded, or even hosted by InKnowledge on the Windows Azure platform, and it’s completely FREE!!

    Here is the preview video:

    359 Views, 0 Comment(s), Published on: 05-27-2011 18:43 by veri to All about GIS
    | More
    Filed under: ,
  • Bing Maps and OData (part 6)

    Dear readers, first of all I wanted to say sorry because my last post about Bing Maps and OData wasn’t really my last post after all because I wanted to try something interesting. I wanted to port my NerdDinner silverlight application to Windows Phone. It’s not that hard actually. All you need to do is just a little bit of tuning because the map control in Windows Phone is a bit different with the Bing Maps Silverlight Control. And don’t forget the most important thing: you can’t add a service reference to OData service like you did in a Silverlight project. So, how can I get the data then? I’ll explain to you how.

    Generating WCF Data Services class

    Untuk bisa menggunakan OData service dari NerdDinner, kalian harus men-generate sendiri data service class-nya dengan cara menggunakan DataSvcUtil.exe. Untuk contoh penggunaannya bisa dilihat di sini. Jadi, kurang lebih yang akan kalian tuliskan di command prompt adalah seperti ini bila versi .NET Framework kalian adalah versi 4 “%windir%\Microsoft.NET\Framework\v4.0.30319\DataSvcUtil.exe” /dataservicecollection /version:2.0 /language:CSharp /out:NerdDinner.cs /uri:http://www.nerddinner.com/Services/OData.svc/

    Setelah selesai di generate, include file NerdDinner.cs hasil generate tadi ke dalam project Windows Phone Anda.

    Untuk keseluruhan projectnya sendiri, tidak banyak berbeda dengan versi silverlight-nya tapi tentu saja tidak akan ada Child Window-nya. Versi Windows Phone ini hanya untuk melihat lokasi dinnernya saja, tidak seperti versi silverlight. Hasil akhirnya akan tampak seperti pada gambar berikut.

    Result

    The source code can be downloaded from here. Enjoy…

    471 Views, 0 Comment(s), Published on: 04-30-2011 10:16 by veri to All about GIS
  • Bing Maps and OData (part 5)

    This is the last post from a series that talked about Bing Maps and OData. I’ve told you how to retrieve and how to consume the OData in here, how to create the ViewModel that will be used for data binding in here, and how to create the Child Window in here. Finally, in this post I will show you how to make the main UX for the NerdDinner web application. Just copy and paste the code below to your MainPage.xaml.

       1: <UserControl x:Class="BingMapsOData.MainPage"
       2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       4:     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
       5:     xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
       6:     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
       7:     xmlns:local="clr-namespace:BingMapsOData"
       8:     xmlns:m="clr-namespace:Microsoft.Maps.MapControl;assembly=Microsoft.Maps.MapControl"
       9:     xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
      10:     mc:Ignorable="d"
      11:     d:DesignHeight="300" d:DesignWidth="400">
      12:     
      13:     <UserControl.Resources>
      14:         <DataTemplate x:Key="DinnerTemplate">
      15:             <m:Pushpin Name="DinnerPushpin" m:MapLayer.Position="{Binding Location}" Content="{Binding Attendees}">
      16:                 <i:Interaction.Triggers>
      17:                     <i:EventTrigger EventName="MouseLeftButtonDown">
      18:                         <local:ShowChildWindowAction ChildWindowType="BingMapsOData.DetailsChildWindow"/>
      19:                     </i:EventTrigger>
      20:                 </i:Interaction.Triggers>
      21:                 <ToolTipService.ToolTip>
      22:                     <StackPanel>
      23:                         <StackPanel Margin="2" Orientation="Horizontal">
      24:                             <Image Source="Images/dinner.png" Width="16" Height="16"/>
      25:                             <TextBlock Text="{Binding Title}" Padding="2" FontWeight="Bold" TextWrapping="Wrap"/>
      26:                         </StackPanel>
      27:                         <TextBlock Text="{Binding Date}" Padding="2" Margin="2" TextWrapping="Wrap"/>
      28:                         <TextBlock Text="{Binding Address}" Padding="2" Margin="2" TextWrapping="Wrap"/>
      29:                         <TextBlock Text="Click Pushpin for details" Foreground="Gray" Padding="2" Margin="2" TextWrapping="Wrap"/>
      30:                     </StackPanel>
      31:                 </ToolTipService.ToolTip>
      32:             </m:Pushpin>
      33:         </DataTemplate>
      34:     </UserControl.Resources>
      35:  
      36:     <Grid x:Name="LayoutRoot" Background="Black">
      37:         <Grid.RowDefinitions>
      38:             <RowDefinition Height="40"/>
      39:             <RowDefinition Height="37"/>
      40:             <RowDefinition Height="*"/>
      41:             <RowDefinition Height="20"/>
      42:         </Grid.RowDefinitions>
      43:         <Grid.ColumnDefinitions>
      44:             <ColumnDefinition />
      45:             <ColumnDefinition Width="Auto" />
      46:         </Grid.ColumnDefinitions>
      47:         
      48:         <m:Map x:Name="dinnerMap"
      49:                Grid.Row="0" Grid.RowSpan="3"
      50:                Grid.Column="0" Grid.ColumnSpan="2"
      51:                CacheMode="BitmapCache"
      52:                CredentialsProvider="{StaticResource MyCredentials}"
      53:                Mode="AerialWithLabels"
      54:                NavigationVisibility="Collapsed">
      55:             <m:MapItemsControl x:Name="dinnerList"
      56:                                ItemTemplate="{StaticResource DinnerTemplate}"
      57:                                ItemsSource="{Binding Dinners}">
      58:             </m:MapItemsControl>
      59:         </m:Map>
      60:  
      61:         <StackPanel Grid.Row="0" Grid.Column="0" Background="Black" Opacity="0.8">
      62:             <StackPanel Orientation="Horizontal">
      63:                 <TextBlock Text="Nerd Dinner Browser" FontSize="20" Padding="6" Foreground="White"/>
      64:                 <TextBlock Text="{Binding Status}" FontSize="14" Padding="12" Foreground="LightGray" Name="txtStatus" >
      65:                     <TextBlock.Triggers>
      66:                     </TextBlock.Triggers>
      67:                 </TextBlock>
      68:             </StackPanel>
      69:         </StackPanel>
      70:  
      71:         <StackPanel Grid.Row="1" Grid.Column="0">
      72:             <Border BorderThickness="1" BorderBrush="LightGray" Background="LightGray" CornerRadius="5" Padding="5" Margin="1">
      73:                 <StackPanel Orientation="Horizontal">
      74:                     <TextBlock Text="Dinners From " Padding="4"/>
      75:                     <controls:DatePicker SelectedDate="{Binding From, Mode=TwoWay}" Name="dtFrom" Width="130"/>
      76:                     <TextBlock Text=" To " Padding="4"/>
      77:                     <controls:DatePicker SelectedDate="{Binding To, Mode=TwoWay}" Name="dtTo" Width="130"/>
      78:                     <TextBlock Text=" Near " Padding="4"/>
      79:                     <TextBox Name="txtPlace" ToolTipService.ToolTip="Optional, Leave blank for a high level view" Width="130"/>
      80:                     <Button Name="SearchDinners" Click="SearchDinners_Click" Margin="1" Padding="3">
      81:                         <StackPanel Orientation="Horizontal" >
      82:                             <Image Source="Images/dinner.png" Width="16" Height="16"/>
      83:                             <TextBlock Text=" Grab The Dinners "/>
      84:                         </StackPanel>
      85:                     </Button>
      86:                     <TextBlock Width="6"/>
      87:                     <StackPanel Background="Gray" Width="2" Margin="2"/>
      88:                 </StackPanel>
      89:             </Border>
      90:         </StackPanel>
      91:  
      92:         <Canvas x:Name="cMiniMap" 
      93:                 Width="150" 
      94:                 Height="150" 
      95:                 HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Grid.Row="2" >
      96:             <m:Map x:Name="MiniMap" 
      97:                    CredentialsProvider="{StaticResource MyCredentials}"
      98:                    CacheMode="BitmapCache"
      99:                    Width="150" 
     100:                    Height="150" 
     101:                    Mode="Road" 
     102:                    NavigationVisibility="Collapsed" 
     103:                    ScaleVisibility="Collapsed" 
     104:                    LogoVisibility="Collapsed"
     105:                    CopyrightVisibility="Collapsed" Foreground="{x:Null}">
     106:                 <m:Map.Clip>
     107:                     <EllipseGeometry RadiusX="69" RadiusY="69" Center="75,75" />
     108:                 </m:Map.Clip>
     109:             </m:Map>
     110:             <Ellipse Width="150" Height="150" Stroke="#CC4C4C4C" StrokeThickness="6" Margin="0,0,0,0" CacheMode="BitmapCache" />
     111:             <Ellipse Height="10" Width="10" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="70,70,0,0" x:Name="ellipse" Fill="#CC205A5B" />
     112:         </Canvas>
     113:  
     114:         <Canvas x:Name="cNavControl" 
     115:                 Width="100" 
     116:                 HorizontalAlignment="Left" 
     117:                 VerticalAlignment="Top" Grid.Row="2" Margin="60,155,0,0" Grid.RowSpan="3" >
     118:             <StackPanel Width="50">
     119:                 <Ellipse x:Name="ePan" Fill="#CC4C4C4C" Height="50" Canvas.ZIndex="1" Width="50"/>
     120:                 <Path x:Name="pathMiniMap" Stretch="Fill" Stroke="#CCFFFFFF" Height="195" Margin="-50,-195,-50,0" UseLayoutRounding="False" Canvas.ZIndex="1" Data="M75,0.5 C116.14521,0.5 149.5,33.854782 149.5,75 C149.5,111.64496 123.04255,142.11044 88.187729,148.3364 L86.852966,148.55754 L87.70414,149.04695 C94.776031,153.34393 99.5,161.1203 99.5,170 C99.5,183.53098 88.530975,194.5 75,194.5 C61.469025,194.5 50.5,183.53098 50.5,170 C50.5,161.1203 55.223965,153.34393 62.29586,149.04695 L63.14703,148.55754 L61.812263,148.3364 C26.957447,142.11044 0.5,111.64496 0.5,75 C0.5,33.854782 33.854786,0.5 75,0.5 z"/>
     121:                 <Grid x:Name="gridPan" Height="50" Margin="0,-50,0,0" Width="50" Canvas.ZIndex="1">
     122:                     <Grid.RowDefinitions>
     123:                         <RowDefinition Height="12"/>
     124:                         <RowDefinition Height="26" />
     125:                         <RowDefinition Height="12"/>
     126:                     </Grid.RowDefinitions>
     127:                     <Grid.ColumnDefinitions>
     128:                         <ColumnDefinition Width="12" />
     129:                         <ColumnDefinition Width="26" />
     130:                         <ColumnDefinition Width="12"/>
     131:                     </Grid.ColumnDefinitions>
     132:  
     133:                     <Image Source="Images/PanUp.png" Stretch="Fill" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Top" Height="20" Margin="0,5,0,0" Width="34" MouseLeftButtonDown="PanMapUp"/>
     134:                     <Image Source="Images/PanLeft.png" Stretch="Fill" Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Center" Width="20" Margin="5,0,0,0" Height="34" MouseLeftButtonDown="PanMapLeft"/>
     135:                     <Image Source="Images/PanRight.png" Stretch="Fill" Grid.Row="1" Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Center" Width="20" Margin="0,0,5,0" Height="34" MouseLeftButtonDown="PanMapRight"/>
     136:                     <Image Source="Images/PanDown.png" Stretch="Fill" Height="20" Margin="0,0,0,5" VerticalAlignment="Bottom" Grid.Row="2" Grid.Column="1" HorizontalAlignment="Center" Width="34" MouseLeftButtonDown="PanMapDown"/>
     137:                 </Grid>
     138:                 <Border Margin="0,5,0,0" Width="15" Background="#CC4C4C4C" BorderThickness="1,1,1,0" BorderBrush="#CCFFFFFF" Height="15">
     139:                     <TextBlock Foreground="White" HorizontalAlignment="Center" Text="+" MouseLeftButtonDown="ZoomIn" VerticalAlignment="Center"/>
     140:                 </Border>
     141:                 <Border Height="160" HorizontalAlignment="Center" Margin="0" Width="15" RenderTransformOrigin="0.5,0.5" BorderThickness="1" Background="#CC4C4C4C" BorderBrush="#CCFFFFFF">
     142:                     <Slider x:Name="sldZoom" Orientation="Vertical" Maximum="21" Minimum="1" Height="150" Value="0" HorizontalAlignment="Center" Margin="0" SmallChange="1" BorderBrush="{x:Null}" BorderThickness="1" Width="15" Canvas.ZIndex="1" Foreground="{x:Null}" >
     143:                         <i:Interaction.Behaviors>
     144:                             <local:SnappingSlider/>
     145:                         </i:Interaction.Behaviors>
     146:                     </Slider>
     147:                 </Border>
     148:                 <Border Margin="0,0,0,5" Width="15" Background="#CC4C4C4C" BorderThickness="1,0,1,1" BorderBrush="#CCFFFFFF" Height="15">
     149:                     <TextBlock Foreground="White" HorizontalAlignment="Center" Text="-" MouseLeftButtonDown="ZoomOut" VerticalAlignment="Center"/>
     150:                 </Border>
     151:                 <Border Margin="0" Width="50" Background="#CC4C4C4C" BorderThickness="1" BorderBrush="#CCFFFFFF">
     152:                     <TextBlock Foreground="White" HorizontalAlignment="Center" Text="Road" MouseLeftButtonDown="MapStyleRoad" VerticalAlignment="Center"/>
     153:                 </Border>
     154:                 <Border Height="15" Margin="0" Width="50" Background="#CC4C4C4C" BorderThickness="1,0,1,1" BorderBrush="#CCFFFFFF">
     155:                     <TextBlock Foreground="White" HorizontalAlignment="Center" Text="Aerial" MouseLeftButtonDown="MapStyleAerial" VerticalAlignment="Center"/>
     156:                 </Border>
     157:                 <Border Height="15" Margin="0" Width="50" Background="#CC4C4C4C" BorderThickness="1,0,1,1" BorderBrush="#CCFFFFFF">
     158:                     <TextBlock Foreground="White" HorizontalAlignment="Center" Text="Hybrid" MouseLeftButtonDown="MapStyleHybrid" VerticalAlignment="Center"/>
     159:                 </Border>
     160:             </StackPanel>
     161:         </Canvas>
     162:  
     163:         <StackPanel Orientation="Horizontal" Grid.Row="3" HorizontalAlignment="Center">
     164:             <HyperlinkButton NavigateUri="http://students.netindonesia.net/blogs/veri" Content="My Blog" TargetName="_blank" FontFamily="Verdana" FontSize="12" Foreground="#FFFFFFFF"/>
     165:             <TextBlock Foreground="White" Text="|"></TextBlock>
     166:             <HyperlinkButton NavigateUri="http://twitter.com/vferdiansyah" Content="Twitter" TargetName="_blank" FontFamily="Verdana" FontSize="12" Foreground="#FFFFFFFF"/>
     167:             <TextBlock Foreground="White" Text="|"></TextBlock>
     168:             <HyperlinkButton NavigateUri="http://www.facebook.com/verif" Content="Facebook" TargetName="_blank" FontFamily="Verdana" FontSize="12" Foreground="#FFFFFFFF"/>
     169:             <TextBlock Foreground="White" Text="|"></TextBlock>
     170:             <HyperlinkButton NavigateUri="http://www.linkedin.com/pub/veri-ferdiansyah/21/a14/593" Content="Linked In" TargetName="_blank" FontFamily="Verdana" FontSize="12" Foreground="#FFFFFFFF"/>
     171:         </StackPanel>
     172:     </Grid>
     173: </UserControl>

    After that, you also need to copy and paste the code below to your MainPage.xaml.cs.

       1: using System;
       2: using System.Windows;
       3: using System.Windows.Browser;
       4: using System.Windows.Controls;
       5: using System.Windows.Input;
       6: using BingMapsOData.Helpers;
       7: using BingMapsOData.ViewModels;
       8: using Microsoft.Maps.MapControl;
       9:  
      10: namespace BingMapsOData
      11: {
      12:     public partial class MainPage : UserControl
      13:     {
      14:         NerdDinnerViewModel vm;
      15:         MapSearchHelper searchHelper = new MapSearchHelper();
      16:         
      17:         public MainPage()
      18:         {
      19:             InitializeComponent();
      20:             InitializeViewModel();
      21:  
      22:             dinnerMap.TargetViewChanged += new EventHandler<MapEventArgs>(dinnerMap_TargetViewChanged);
      23:  
      24:             sldZoom.Value = dinnerMap.ZoomLevel;
      25:             sldZoom.ValueChanged += new RoutedPropertyChangedEventHandler<double>(ZoomChange);
      26:  
      27:             MiniMap.MouseClick += new EventHandler<MapMouseEventArgs>(MiniMap_MouseClick);
      28:             MiniMap.MouseDoubleClick += new EventHandler<MapMouseEventArgs>(MiniMap_MouseDoubleClick);
      29:             MiniMap.MouseDragBox += new EventHandler<MapMouseDragEventArgs>(MiniMap_MouseDragBox);
      30:             MiniMap.MousePan += new EventHandler<MapMouseDragEventArgs>(MiniMap_MousePan);
      31:             MiniMap.MouseWheel += new System.Windows.Input.MouseWheelEventHandler(MiniMap_MouseWheel);
      32:             MiniMap.KeyUp += new System.Windows.Input.KeyEventHandler(MiniMap_KeyUp);
      33:             MiniMap.KeyDown += new System.Windows.Input.KeyEventHandler(MiniMap_KeyDown);
      34:             MiniMap.KeyPress += new EventHandler<MapKeyPressEventArgs>(MiniMap_KeyPress);
      35:             MiniMap.KeyHeld += new EventHandler<MapKeyHeldEventArgs>(MiniMap_KeyHeld);
      36:             MiniMap.SetView(dinnerMap.TargetCenter, Math.Max(1.0, dinnerMap.TargetZoomLevel - 5));
      37:         }
      38:  
      39:         #region MainPage Events
      40:  
      41:         private void dinnerMap_TargetViewChanged(object sender, MapEventArgs e)
      42:         {
      43:             MiniMap.SetView(dinnerMap.TargetCenter, Math.Max(1.0, dinnerMap.TargetZoomLevel - 5));
      44:             sldZoom.Value = dinnerMap.TargetZoomLevel;
      45:         }
      46:  
      47:         #endregion
      48:  
      49:         #region MiniMap Events
      50:  
      51:         private void MiniMap_KeyHeld(object sender, MapKeyHeldEventArgs e)
      52:         {
      53:             e.Handled = true;
      54:         }
      55:  
      56:         private void MiniMap_KeyPress(object sender, MapKeyPressEventArgs e)
      57:         {
      58:             e.Handled = true;
      59:         }
      60:  
      61:         private void MiniMap_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
      62:         {
      63:             e.Handled = true;
      64:         }
      65:  
      66:         private void MiniMap_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
      67:         {
      68:             e.Handled = true;
      69:         }
      70:  
      71:         private void MiniMap_MouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
      72:         {
      73:             e.Handled = true;
      74:         }
      75:  
      76:         private void MiniMap_MousePan(object sender, MapMouseDragEventArgs e)
      77:         {
      78:             e.Handled = true;
      79:         }
      80:  
      81:         private void MiniMap_MouseDragBox(object sender, MapMouseDragEventArgs e)
      82:         {
      83:             e.Handled = true;
      84:         }
      85:  
      86:         private void MiniMap_MouseDoubleClick(object sender, MapMouseEventArgs e)
      87:         {
      88:             e.Handled = true;
      89:         }
      90:  
      91:         private void MiniMap_MouseClick(object sender, MapMouseEventArgs e)
      92:         {
      93:             e.Handled = true;
      94:         }
      95:  
      96:         #endregion
      97:  
      98:         #region Map Navigation
      99:  
     100:         private void ZoomChange(object sender, RoutedPropertyChangedEventArgs<double> e)
     101:         {
     102:             dinnerMap.ZoomLevel = sldZoom.Value;
     103:         }
     104:  
     105:         private void ZoomIn(object sender, MouseButtonEventArgs e)
     106:         {
     107:             dinnerMap.ZoomLevel = dinnerMap.TargetZoomLevel + 1;
     108:         }
     109:  
     110:         private void ZoomOut(object sender, MouseButtonEventArgs e)
     111:         {
     112:             dinnerMap.ZoomLevel = dinnerMap.TargetZoomLevel - 1;
     113:         }
     114:  
     115:         private void PanMapLeft(object sender, MouseButtonEventArgs e)
     116:         {
     117:             dinnerMap.Center = dinnerMap.ViewportPointToLocation(new Point(dinnerMap.ViewportSize.Width / 2 - 50, dinnerMap.ViewportSize.Height / 2));
     118:         }
     119:  
     120:         private void PanMapRight(object sender, MouseButtonEventArgs e)
     121:         {
     122:             dinnerMap.Center = dinnerMap.ViewportPointToLocation(new Point(dinnerMap.ViewportSize.Width / 2 + 50, dinnerMap.ViewportSize.Height / 2));
     123:         }
     124:  
     125:         private void PanMapUp(object sender, MouseButtonEventArgs e)
     126:         {
     127:             dinnerMap.Center = dinnerMap.ViewportPointToLocation(new Point(dinnerMap.ViewportSize.Width / 2, dinnerMap.ViewportSize.Height / 2 - 50));
     128:         }
     129:  
     130:         private void PanMapDown(object sender, MouseButtonEventArgs e)
     131:         {
     132:             dinnerMap.Center = dinnerMap.ViewportPointToLocation(new Point(dinnerMap.ViewportSize.Width / 2, dinnerMap.ViewportSize.Height / 2 + 50));
     133:         }
     134:  
     135:         private void MapStyleRoad(object sender, MouseButtonEventArgs e)
     136:         {
     137:             dinnerMap.Mode = new RoadMode();
     138:         }
     139:  
     140:         private void MapStyleAerial(object sender, MouseButtonEventArgs e)
     141:         {
     142:             dinnerMap.Mode = new AerialMode(false);
     143:         }
     144:  
     145:         private void MapStyleHybrid(object sender, MouseButtonEventArgs e)
     146:         {
     147:             dinnerMap.Mode = new AerialMode(true);
     148:         }
     149:  
     150:         #endregion
     151:  
     152:         /// <summary>
     153:         /// Initialize our view model, and assign it to the view
     154:         /// </summary>
     155:         private void InitializeViewModel()
     156:         {
     157:             vm = new NerdDinnerViewModel();
     158:             this.DataContext = vm;
     159:             try
     160:             {
     161:                 vm.QueryDinners();
     162:             }
     163:             catch (Exception ex)
     164:             {
     165:                 MessageBox.Show("Error loading the dinners. Make sure you are online. " + ex.Message);
     166:             }
     167:         }
     168:  
     169:         private void SearchDinners_Click(object sender, RoutedEventArgs e)
     170:         {
     171:             try
     172:             {
     173:                 if (!string.IsNullOrEmpty(txtPlace.Text))
     174:                     searchHelper.ExecuteSearch(txtPlace.Text, this.dinnerMap);
     175:             }
     176:             catch (Exception ex)
     177:             {
     178:                 MessageBox.Show("Error zooming in to " + txtPlace.Text + ex.Message);
     179:             }
     180:  
     181:             try
     182:             {
     183:                 vm.QueryDinners();
     184:             }
     185:             catch (Exception ex)
     186:             {
     187:                 MessageBox.Show("Error loading the dinners. Make sure you are online. " + ex.Message);
     188:             }
     189:         }
     190:     }
     191: }

    Don’t forget to change the Bing Maps credentials in App.xaml with your own key. Hit F5 and your NerdDinner web application is ready to go!

    Result

    You can download the sample code in here. Enjoy…

    453 Views, 1 Comment(s), Published on: 04-25-2011 8:51 by veri to All about GIS
    | More
  • 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..

    276 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…

    568 Views, 4 Comment(s), Published on: 03-02-2011 4:34 by veri to All about GIS
    | More
    Filed under: , , , ,
  • Bing Maps and OData (Part 1)

    Setelah lama gak eksplorasi teknologi karena berbagai kesibukan seperti mengurus acara Arkavidia 2.0 dan terutama adalah Tugas Akhir atau yang biasa disebut sebagai skripsi, akhirnya ada sedikit waktu untuk eksplorasi juga. Pada postingan yang akan terdiri dari beberapa bagian kali ini, saya akan menjelaskan tentang OData dan integrasi OData pada Bing Maps.

    Open Data Protocol

    Open Data Protocol, atau yang biasa disebut dengan OData, merupakan sebuah web protocol untuk melakukan query dan update data yang menyajikan sebuah cara baru untuk meng-unlock data dan membersihkannya dari “silo” yang biasa terdapat dalam aplikasi-aplikasi saat ini. OData dibuat berdasarkan teknologi web seperti HTTP, Atom Publishing Protocol (AtomPub), dan JSON untuk menyediakan akses terhadap informasi dari berbagai sumber seperti basis data relasional, file system, content management system, dan website-website tradisional.

    WCF Data Services

    WCF Data Services (sebelumnya bernama ADO.NET Data Services atau Astoria), merupakan teknologi Microsoft pertama yang mendukung OData di Visual Studio 2008 SP1. Saat ini, Microsoft juga mendukung OData di SQL Server 2008 R2, Windows Azure Storage, Excel 2010 (melalui PowerPivot), dan SharePoint 2010.

    aa937697_DS_AtAGlance_2a(en-us,MSDN_10)

    Oke, sekarang kita sudah mengetahui sekilas tentang apa itu OData dan WCF Data Services. Pada postingan selanjutnya, saya akan menjelaskan tentang membuat aplikasi Bing Maps yang mengkonsumsi data dari OData. Ciao for now…

    523 Views, 4 Comment(s), Published on: 02-28-2011 9:53 by veri to All about GIS
    | More
    Filed under: , ,
  • Arkavidia 2.0

    Arkavidia 2.0 merupakan sebuah acara besar di bidang IT hasil karya Himpunan Mahasiswa Informatika ITB. Acara tersebut akan berlangsung pada tanggal 19-20 Februari 2011 dan bertempat di dalam kampus ITB. Acara Arkavidia 2.0 ini terdiri dari beberapa acara kecil antara lain:

    • Lomba
    • Seminar
    • Expo
    • Career Day
    • Gerakan Seribu Jari

    Di lomba, kita bisa belajar berkompetisi. Di seminar, kita bisa dapet ilmu mengenai IT untuk masa sekarang dan yang akan datang. Di expo, kita bisa liat karya-karya mahasiswa terutama mahasiswa IF ITB. Di career day, kita bisa mencari info tentang pekerjaan di perusahaan-perusahaan bonafit. Di gerakan seribu jari, kita bisa beramal untuk sesama.

    Selain itu, bakal ada juga performance dari band-band terkenal loh! Salah satunya adalah Mocca. So, buat kalian para penggemar Mocca, pasti rugi banget deh klo gak dateng…

    So, jangan lupa dateng ya ke acara Arkavidia 2.0 ini kawan-kawan.

    171532_1826644794182_1482175738_1996880_7661617_o

    468 Views, 3 Comment(s), Published on: 02-15-2011 11:02 by veri to All about GIS
    | More
    Filed under:
  • News Reader for Windows Phone

    Dear all, recently I have made a news reader application for Windows Phone. With this application, you can read news from Detik, Kompas Cybermedia, Okezone, and Metrotv News. You also can list some news as your favorite and if you don’t want to waste your time searching a whole list for news that you want to read, just type some word in the search box and the application will do the rest. Below is the screencast for this application. Enjoy…

    News Reader for Windows Phone
    306 Views, 1 Comment(s), Published on: 01-30-2011 19:03 by veri to All about GIS
    | More
    Filed under: , ,
  • Windows Phone 7 Map and Pivot Control

    Pada 2 postingan sebelumnya, yang dapat dilihat disini dan disini, saya telah menjelaskan tentang Map control pada Windows Phone 7. Nah, pada postingan kali ini, saya masih akan membahas tentang Map control pada Windows Phone 7 namun dalam aplikasi yang menggunakan Pivot control.

    Pivot Control

    Pivot Control merupakan sebuah control pada Windows Phone yang mempercepat pengaturan view atau halaman. Control ini bisa digunakan untuk memfilter dataset yang besar, menampilkan banyak dataset, atau berpindah-pindah antar view dalam satu aplikasi.

    Dasar dari sebuah aplikasi berbasis Pivot adalah sebuah Pivot control yang merupakan container untuk secondary control yang disebut PivotItem. PivotItem ini mengandung konten-konten seperti grid, link, atau dalam kasus ini sebuah map dalam tiap halamannya.

    IC425811

    Pivot Control Navigation

    Untuk menavigasikan Pivot control ini, kalian tidak perlu mengimplementasikan special gesture apapun pada aplikasi kalian karena Pivot control ini, by default, sudah dibekali dengan built-in touch interaction. Touch interaction yang didukung oleh control ini antara lain:

    • Horizontal pan
    • Horizontal flick
    • Navigating hosted controls

    Problem

    Permasalahan utama dalam menempatkan sebuah control yang mensupport flick interaction seperti Map pada Pivot adalah bila Anda melakukan flick pada Map searah dengan Pivot, maka tampilan pada layar akan berpindah ke halaman sebelum/setelahnya tergantung dari arah flick Anda.

    Cobalah buat sebuah aplikasi Pivot pada Visual Studio 2010, dan masukkan Map control ke dalam halaman pertama. Jalankan aplikasi Anda dan cobalah untuk menavigasikan Map-nya. Anda akan menemukan dua buah bug yaitu:

    • Saat menavigasikan Map, aplikasi Anda akan crash
    • Saat Anda melakukan fast flick pada Map, maka halaman pada layar akan berpindah

    Solution

    Solusi untuk menyelesaikan permasalahan tersebut adalah dengan menggunakan fungsi IsHitTestVisible yang merupakan sebuah fungsi boolean dari WPF yang dapat meng-enable atau men-disable nilai true yang muncul bila touch event terjadi pada sebuah komponen. Jadi, bila Anda menset properti IsHitTestVisible pada sebuah Pivot menjadi false saat terdapat event MouseLeftButtonDown pada Map, maka Anda dapat menavigasikan Map dengan bebas tanpa perlu khawatir akan berpindah halaman.

    Aplikasi ini bisa Anda download disini. Enjoy…

    413 Views, 1 Comment(s), Published on: 01-07-2011 8:10 by veri to All about GIS
    | More
  • Bing Maps and Facebook API

    Kalian semua pasti tau apa itu Facebook kan? Kayaknya gak mungkin deh anak muda Indonesia zaman sekarang gak punya account Facebook atau malah gak tau apa itu Facebook. Buat yang belum tau, Facebook itu adalah sebuah situs social networking seperti Friendster yang dibuat oleh Mark Zuckerberg, seorang mahasiswa yang di DO dari Harvard. Hebat ya mahasiswa DO Harvard bisa bikin Facebook dan sekarang jadi salah satu multi-millionaire termuda di dunia dan baru-baru ini, dia terpilih sebagai “People of the Year” versi majalah Times.

    Nah, kalian yang sering buka Facebook pasti pernah menggunakan salah satu aplikasi yang menanyakan kepada kalian apakah kalian setuju untuk memberikan izin kepada aplikasi tersebut untuk mengakses data-data pribadi kalian seperti yang terlihat pada gambar berikut.

    api_facebook14

    Atau seperti pada gambar berikut.

    n20531316728_1757356_1276

    Sebenarnya itu apa sih? Bagi kalian yang belum tau, kedua gambar diatas merupakan contoh-contoh aplikasi yang menggunakan Facebook Connect, sebuah metode autentikasi untuk mengakses data-data user yang ada pada Facebook. Jadi, dengan memberikan izin kepada sebuah aplikasi untuk mengakses profil Anda, berarti Anda telah memberikan izin kepada aplikasi tersebut untuk melihat data-data pribadi Anda. Oleh karena itu, berhati-hatilah terhadap aplikasi-aplikasi “nakal” yang bisa menyalahgunakan informasi yang Anda berikan.

    Karena sedang liburan, saya membuat sebuah aplikasi map sederhana yang memanfaatkan Facebook API untuk mengakses data pribadi Anda seperti nama lengkap, about me dan current location yang Anda tulis pada profil Facebook Anda. Setelah Anda melakukan login dan menyetujui bahwa aplikasi ini akan mengakses data pribadi Anda, maka pada map akan muncul sebuah pushpin yang terletak di kota tempat ada berada sekarang (menurut profil Facebook) yang memiliki tooltip berupa nama lengkap dan about me pada profil Facebook Anda yang akan muncul apabila Anda melakukan aksi Mouse Over pada pushpin tersebut.

    Untitled

    Aplikasi ini bisa Anda coba sendiri dengan mengunduhnya disini. Sebelumnya saya ingin memberitahukan bahwa aplikasi ini hanya mengakses nama lengkap, lokasi, dan about me pada profil Facebook Anda. Selain itu, saya juga tidak akan menyalahgunakan data-data tersebut karena aplikasi ini hanya saya buat untuk sekedar mengisi waktu luang dan berbagi ilmu saja.

    Bagi yang penasaran, Anda cukup membuka solutionnya di Visual Studio 2010 dan menekan F5 untuk menjalankan aplikasinya. Lalu login, dan berikan izin kepada aplikasi untuk mengakses data pribadi Anda. Enjoy…

    683 Views, 1 Comment(s), Published on: 01-03-2011 5:36 by veri to All about GIS
    | More
    Filed under: , , , ,
More Posts Next page »