Skip to main content

DevExpress v24.2 Update — Your Feedback Matters

Our What's New in v24.2 webpage includes product-specific surveys. Your response to our survey questions will help us measure product satisfaction for features released in this major update and help us refine our plans for our next major release.

Take the survey Not interested

How to: Implement a Custom Search Provider

  • 4 minutes to read

This example demonstrates how to create a custom search provider.

To do this, design a class inheriting the InformationDataProviderBase abstract class and implement the CreateData() method in it. Then, create a class inheriting the IInformationData interface and override its IInformationData.OnDataResponse event. Implement the Search(string keyword) method to provide custom search logic.

using DevExpress.XtraMap;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CustomSearchProvider {
    public partial class Form1 : Form {
        InformationLayer Layer { get { return (InformationLayer)mapControl1.Layers[1]; } }
        public Form1() {
            InitializeComponent();
            SearchProvider provider = new SearchProvider();
            Layer.DataProvider = provider;
        }
    }
    public class SearchProvider : InformationDataProviderBase, ISearchPanelRequestSender {
        protected new SearchData Data { get { return (SearchData)base.Data; } }
        public IEnumerable<LocationInformation> Addresses { get { return Data.Addresses; } }
        protected override IInformationData CreateData() {
            return new SearchData();
        }
        public void SearchByString(string keyword) {
            Data.Search(keyword);
        }
    }
    public class SearchData : IInformationData {
        readonly List<LocationInformation> addresses = new List<LocationInformation>();
        public IEnumerable<LocationInformation> Addresses { get { return addresses; } }
        public event EventHandler<RequestCompletedEventArgs> OnDataResponse;
        readonly TaskScheduler scheduler;
        public SearchData() {
            scheduler = TaskScheduler.FromCurrentSynchronizationContext();
        }
        RequestCompletedEventArgs CreateEventArgs() {
            MapItem[] items = new MapItem[addresses.Count];
            for (int i = 0; i < items.Length; i++)
                items[i] = new MapCallout() { Location = addresses[i].Location, Text = addresses[i].Address.FormattedAddress };
            return new RequestCompletedEventArgs(items, null, false, null);
        }
        protected void RaiseChanged() {
            if (OnDataResponse != null)
                OnDataResponse(this, CreateEventArgs());
        }
        public void Search(string keyword) {
            Task.Factory.StartNew(async () => {
                Random rnd = new Random(DateTime.Now.Millisecond);
                addresses.Clear();
                int length = keyword.Length;
                for (int i = 0; i < length; i++) {
                    LocationInformation info = new LocationInformation();
                    info.Address = new Address(keyword + " " + i.ToString());
                    info.Location = new GeoPoint(rnd.Next(180) - 90, rnd.Next(360) - 180);
                    addresses.Add(info);
                }
                await Task.Delay(500);
                RaiseChanged();
            }, CancellationToken.None, TaskCreationOptions.LongRunning | TaskCreationOptions.DenyChildAttach, scheduler);
        }
    }
    public class Address : AddressBase {
        public Address(string address) {
            this.FormattedAddress = address;
        }
    }
}