Implementing Favourite Views for the XamMap Component

[Infragistics] Mihail Mateev / Friday, August 6, 2010

People often wants to keep a list of "favourite places" on their map.

This article describes how to implement persistence of the favourite views with the Infragistics XamMap control for Silverlight.

The sample application is based on the Silverlight sample, used for the article Using Infragistics XamMap Silverlight/WPF control with SQL Server Spatial

Steps to implement a sample application:

  1. Create a Silverlight application with XamMap, that uses a data from SQL Server Spatial 2008 - steps are described the  article Using Infragistics XamMap Silverlight/WPF control with SQL Server Spatial
  2. Add a class MapRect, containing a Rect, that keeps the current WindowRect of the XamMap component and a description for the view.
  3. Add in the Silverlight application a property, named Favourites from type ObservableCollection<MapRect>.
  4. Implement add and remove a favourite view from the collection.
  5. Implement write and read the favourites list in the Isolated Storage.

 

  •  Implement a Sample Silverlight Application:

 

Sample Silverlight application

  •  Add a class MapRect, containing a Rect, that keeps the current WindowRect of the XamMap component and a description for the view.

/// <summary>

/// Implements a data to store a favourite view

/// </summary>

public class MapRect: INotifyPropertyChanged

{

    #region Members

    private Rect _windowRect;

    private string _description;

    #endregion //members

 

    #region Properties

    #region WindowRect

    /// <summary>

    /// Gets or sets the window rect.

    /// </summary>

    /// <value>The window rect.</value>

    public Rect WindowRect

    {

        get

        {

            return this._windowRect;

        }

 

        set

        {

            this._windowRect = value;

            OnPropertyChanged("WindowRect");

        }

    }

    #endregion //WindowRect

 

    #region Description

    /// <summary>

    /// Gets or sets the description of a favourite.

    /// </summary>

    /// <value>The description.</value>

    public string Description

    {

        get { return this._description; }

        set

        {

            this._description = value;

            OnPropertyChanged("Description");

        }

    }

    #endregion // Description           

    #endregion  //Properties

 

    #region INotifyPropertyChanged

 

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)

    {

        PropertyChangedEventHandler handler = this.PropertyChanged;

        if (handler != null)

        {

            handler(this, new PropertyChangedEventArgs(propertyName));

        }

 

    }

 

    #endregion //INotifyPropertyChanged

 

}

  •  Add in the Silverlight application a property, named Favourites from type ObservableCollection<MapRect>.

/// <summary>

/// Gets the Favourites collection.

/// </summary>

/// <value>The Favourites.</value>

public ObservableCollection<MapRect> Favourites

{

    get { return this._favourites; }

}

Add a ComboBox, bound to the Favourites property:

<ComboBox Grid.Row="4" x:Name="xMapFavourites" Margin="0,10,0,0" DisplayMemberPath="Description" ItemsSource="{Binding Favourites, ElementName=MainWindow}"

           SelectionChanged="XMapFavouritesSelectionChanged" Foreground="Black">                 

 

  •  Implement add and remove a favourite view from the collection

 Add a buttons to add and remove a MapRect from Favourites collection:

<Button x:Name="BtnAdd" Content="Add" Click="BtnAdd_Click" />

<Button x:Name="BtnRemove" Grid.Column="1" Content="Remove" Click="BtnRemove_Click" />

Implement code to add and remove favourites in event handlers:

 

private void BtnAdd_Click(object sender, RoutedEventArgs e)

{

    MapRect rect = new MapRect { WindowRect = xamMap.WindowRect, Description = "Unknown" };

    this.AddFavouriteWindow.DataContext = rect;

    this.AddFavouriteWindow.Show();

}

 

private void BtnRemove_Click(object sender, RoutedEventArgs e)

{

    if(this.xMapFavourites!=null && this.xMapFavourites.SelectedItem != null)

    {

        MapRect rect = this.xMapFavourites.SelectedItem as MapRect;

        this.Favoirites.Remove(rect);

    }

}

 

XamDialogWinodow, named AddFavouritesWindow uses as DataContext a created MapRect instance,
that keeps a data for the saved view:

 

<ig:XamDialogWindow x:Name="AddFavouriteWindow" WindowState="Hidden" StartupPosition="Center" RestrictInContainer="True" IsModal="True">

    <Grid Width="200" Height="70">

        <Grid.ColumnDefinitions>

            <ColumnDefinition/>

            <ColumnDefinition/>

        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>

            <RowDefinition/>

            <RowDefinition/>

        </Grid.RowDefinitions>

        <sdk:Label Content="Enter Name" VerticalAlignment="Center"/>

        <TextBox Grid.Column="1" x:Name="TxtName" Text="{Binding Description, Mode=TwoWay}" VerticalAlignment="Center"/>

        <Button x:Name="BtnSubmit" Content="Add Favourite" Grid.Row="1" Grid.ColumnSpan="2" Click="BtnSubmit_Click"/>

    </Grid>

</ig:XamDialogWindow>

 

private void BtnSubmit_Click(object sender, RoutedEventArgs e)

{

    MapRect rect = AddFavouriteWindow.DataContext as MapRect;

    if (rect == null)

    {

        return;

    }

 

    this.Favoirites.Add(rect);

    ComboBox combo = this.FindName("xMapFavourites") as ComboBox;

    if (combo != null && combo.Items.Contains(rect))

    {

        combo.SelectedItem = rect;

    }

 

    this.AddFavouriteWindow.Close();

    this.AddFavouriteWindow.DataContext = null;

}

 to do

  • Implement write and read the favourites list in the Isolated Storage.

 Add a buttons to save and load the Favourites collection:

There is used a code to write and load from an Isolated Storage from the article Introduction to the Infragistics Compression Library

 

<Button x:Name="BtnSave" Grid.Row="1" Content="Save" Click="BtnSave_Click" />

<Button x:Name="BtnLoad" Grid.Row="1" Grid.Column="1" Content="Load" Click="BtnLoad_Click" />

 

private void BtnSave_Click(object sender, RoutedEventArgs e)

{

    XmlSerializer xs = new XmlSerializer(typeof(ObservableCollection<MapRect>));

    MemoryStream str = new MemoryStream();

    StreamWriter sr = new StreamWriter(str);

    xs.Serialize(sr, this._favoirites);

    WriteDataToStore(str.ToArray(), IsoFile);

 

}

 

 

// Writes a file to an Isolated Storage, specified via its name

// and content like a byte array

private static void WriteDataToStore(byte[] data, string fileName)

{

    if (data == null || data.Length == 0)

        return;

    using (var store = IsolatedStorageFile.GetUserStoreForApplication())

    {

        CleanStorage(store);

 

        IsolatedStorageFileStream fileStream = store.CreateFile(fileName);

        fileStream.Write(data, 0, data.Length);

        fileStream.Close();

 

    }

}

 

private void BtnLoad_Click(object sender, RoutedEventArgs e)

{

    XmlSerializer xs = new XmlSerializer(typeof(ObservableCollection<MapRect>));

 

    Stream str = new MemoryStream(ReadDataFromStore(IsoFile));

    using (StreamReader rd = new StreamReader(str))

    {

        ObservableCollection<MapRect> favourites = xs.Deserialize(rd) as ObservableCollection<MapRect>;

        if(favourites != null)

        {

            this._favoirites.Clear();

            foreach(MapRect rect in favourites)

            {

                this._favoirites.Add(rect);

            }

        }

    }

}

 

//Reads a file from the Isolated Storage, specified by name

private static byte[] ReadDataFromStore(string fileName)

{

    using (var store = IsolatedStorageFile.GetUserStoreForApplication())

    {

        IsolatedStorageFileStream fileStream;

        fileStream = store.OpenFile(fileName, FileMode.Open);

        byte[] b = new byte[fileStream.Length];

        fileStream.Read(b, 0, (int)fileStream.Length);

        fileStream.Close();

        return b;

    }

}

 

  • Run the sample application:

Select a view.

 Add the current view to favourites.

 

Added view can be selected from the ComboBox with a list of favourites.

 Conclusion:

A favourites support is a very often expected feature in the GIS applications.
It is very easy to implement it in a Silverlight application with a XamMap component.

 Source code of the demo application you could find here: