Back to Devexpress

How to: Implement a Custom Search Provider

wpf-118765-controls-and-libraries-map-control-examples-gis-data-searching-how-to-implement-a-custom-search-provider.md

latest9.7 KB
Original Source

How to: Implement a Custom Search Provider

  • Jun 07, 2019
  • 4 minutes to read

This example demonstrates how to create a custom search provider.

To do this, design a class that inherits the InformationDataProviderBase class and implement the CreateData method in it. Then, design a class that inherits the IInformationData interface and override its IInformationData.OnDataResponse event. Implement the Search method to provide custom search logic.

xaml
<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:CustomSearchProvider"
        xmlns:dxm="http://schemas.devexpress.com/winfx/2008/xaml/map" 
        x:Class="CustomSearchProvider.MainWindow"
        mc:Ignorable="d"
        Title="MainWindow" Height="503" Width="521">
    <Grid>
        <dxm:MapControl x:Name="mapControl">
            <dxm:ImageLayer>
                <dxm:OpenStreetMapDataProvider/>
            </dxm:ImageLayer>
            <dxm:InformationLayer x:Name="infoLayer"/>
        </dxm:MapControl>
    </Grid>
</Window>
csharp
using DevExpress.Xpf.Map;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace CustomSearchProvider {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();
            infoLayer.DataProvider = new SearchProvider();
        }
    }
    public class SearchProvider : InformationDataProviderBase, ISearchPanelRequestSender {
        protected new SearchData Data { get { return (SearchData)base.Data; } }
        public IEnumerable<LocationInformation> Addresses { get { return Data.Addresses; } }

        public override bool IsBusy {
            get { return false; }
        }
        protected override IInformationData CreateData() {
            return new SearchData();
        }
        public void SearchByString(string keyword) {
            Data.Search(keyword);
        }
        public override void Cancel() {
            throw new NotImplementedException();
        }
        protected override MapDependencyObject CreateObject() {
            return new SearchProvider();
        }
    }
    public class SearchData : IInformationData {
        readonly List<LocationInformation> addresses = new List<LocationInformation>();
        public IEnumerable<LocationInformation> Addresses { get { return addresses; } }
        public event EventHandler<RequestCompletedEventArgs> OnDataResponse;
        RequestCompletedEventArgs CreateEventArgs() {
            MapItem[] items = new MapItem[addresses.Count];
            for (int i = 0; i < items.Length; i++)
                items[i] = new MapPushpin() { Location = addresses[i].Location, Information = addresses[i].Address.FormattedAddress, Text = (i + 1).ToString() };
            return new RequestCompletedEventArgs(items, null, false, null);
        }
        protected void RaiseChanged() {
            if (OnDataResponse != null)
                OnDataResponse(this, CreateEventArgs());
        }
        public void Search(string keyword) {
            Random rnd = new Random(DateTime.Now.Millisecond);
            addresses.Clear();
            int length = keyword.Length;
            for (int i = 0; i < length; i++) {
                LocationInformation info = new LocationInformation();
                string address = keyword + " " + i.ToString();
                info.Address = new Address(address);
                info.Location = new GeoPoint(rnd.Next(180) - 90, rnd.Next(360) - 180);
                info.DisplayName = address;
                addresses.Add(info);
            }
            RaiseChanged();
        }
    }
    public class Address : AddressBase {
        public Address(string address) {
            this.FormattedAddress = address;
        }
        protected override MapDependencyObject CreateObject() {
            return new Address(this.FormattedAddress);
        }
    }
}
vb
Imports System
Imports System.Collections.Generic
Imports System.Configuration
Imports System.Data
Imports System.Linq
Imports System.Threading.Tasks
Imports System.Windows

Namespace CustomSearchProvider
    ''' <summary>
    ''' Interaction logic for App.xaml
    ''' </summary>
    Partial Public Class App
        Inherits Application

    End Class
End Namespace
xaml
<Application x:Class="CustomSearchProvider.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:CustomSearchProvider"
             StartupUri="MainWindow.xaml">
    <Application.Resources>

    </Application.Resources>
</Application>
vb
Imports DevExpress.Xpf.Map
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Threading.Tasks
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Data
Imports System.Windows.Documents
Imports System.Windows.Input
Imports System.Windows.Media
Imports System.Windows.Media.Imaging
Imports System.Windows.Navigation
Imports System.Windows.Shapes

Namespace CustomSearchProvider
    ''' <summary>
    ''' Interaction logic for MainWindow.xaml
    ''' </summary>
    Partial Public Class MainWindow
        Inherits Window

        Public Sub New()
            InitializeComponent()
            infoLayer.DataProvider = New SearchProvider()
        End Sub
    End Class
    Public Class SearchProvider
        Inherits InformationDataProviderBase
        Implements ISearchPanelRequestSender

        Protected Shadows ReadOnly Property Data() As SearchData
            Get
                Return CType(MyBase.Data, SearchData)
            End Get
        End Property
        Public ReadOnly Property Addresses() As IEnumerable(Of LocationInformation) Implements ISearchPanelRequestSender.Addresses
            Get
                Return Data.Addresses
            End Get
        End Property

        Public Overrides ReadOnly Property IsBusy() As Boolean
            Get
                Return False
            End Get
        End Property
        Protected Overrides Function CreateData() As IInformationData
            Return New SearchData()
        End Function
        Public Sub SearchByString(ByVal keyword As String) Implements ISearchPanelRequestSender.SearchByString
            Data.Search(keyword)
        End Sub
        Public Overrides Sub Cancel()
            Throw New NotImplementedException()
        End Sub
        Protected Overrides Function CreateObject() As MapDependencyObject
            Return New SearchProvider()
        End Function
    End Class
    Public Class SearchData
        Implements IInformationData

        Private ReadOnly addresses_Renamed As New List(Of LocationInformation)()
        Public ReadOnly Property Addresses() As IEnumerable(Of LocationInformation)
            Get
                Return addresses_Renamed
            End Get
        End Property
        Public Event OnDataResponse As EventHandler(Of RequestCompletedEventArgs) Implements IInformationData.OnDataResponse
        Private Function CreateEventArgs() As RequestCompletedEventArgs
            Dim items(addresses_Renamed.Count - 1) As MapItem
            For i As Integer = 0 To items.Length - 1
                items(i) = New MapPushpin() With { _
                    .Location = addresses_Renamed(i).Location, _
                    .Information = addresses_Renamed(i).Address.FormattedAddress, _
                    .Text = (i + 1).ToString() _
                }
            Next i
            Return New RequestCompletedEventArgs(items, Nothing, False, Nothing)
        End Function
        Protected Sub RaiseChanged()
            RaiseEvent OnDataResponse(Me, CreateEventArgs())
        End Sub
        Public Sub Search(ByVal keyword As String)
            Dim rnd As New Random(Date.Now.Millisecond)
            addresses_Renamed.Clear()
            Dim length As Integer = keyword.Length
            For i As Integer = 0 To length - 1
                Dim info As New LocationInformation()
                Dim address As New String(keyword & " " & i.ToString())
                info.Address = New Address(address)
                info.Location = New GeoPoint(rnd.Next(180) - 90, rnd.Next(360) - 180)
                info.DisplayName = address
                addresses_Renamed.Add(info)
            Next i
            RaiseChanged()
        End Sub
    End Class
    Public Class Address
        Inherits AddressBase

        Public Sub New(ByVal address As String)
            Me.FormattedAddress = address
        End Sub
        Protected Overrides Function CreateObject() As MapDependencyObject
            Return New Address(Me.FormattedAddress)
        End Function
    End Class
End Namespace