Back to Devexpress

LayerBase.ViewportChanged Event

wpf-devexpress-dot-xpf-dot-map-dot-layerbase.md

latest8.8 KB
Original Source

LayerBase.ViewportChanged Event

Occurs every time the current viewport is changed.

Namespace : DevExpress.Xpf.Map

Assembly : DevExpress.Xpf.Map.v25.2.dll

NuGet Package : DevExpress.Wpf.Map

Declaration

csharp
public event ViewportChangedEventHandler ViewportChanged
vb
Public Event ViewportChanged As ViewportChangedEventHandler

Event Data

The ViewportChanged event's data class is ViewportChangedEventArgs. The following properties provide information specific to this event:

PropertyDescription
AngleReturns the Map Control’s rotation angle in degrees.
BottomRightReturns the bottom-right coordinate of the current viewport.
IsAnimated
TopLeftReturns the top-left coordinate of the current viewport.
ZoomLevelReturns the zoom level of the current viewport.

Remarks

How to Detect Visible Items

The following example shows how to determine the number of visible vector items (in this example, map dots) on the map surface. A list box contains the coordinates of the visible items and a text label displays their number. The list of visible items is re-calculated when the map viewport is changed. For example, when a user zooms the map.

To do so, handle the ViewportChanged event of the layer that contains vector items. In the event handler, determine whether item coordinates are in the viewport. The viewport boundaries are defined by the e.TopLeft and e.BottomRight properties:

xaml
<dx:ThemedWindow xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
    xmlns:dxm="http://schemas.devexpress.com/winfx/2008/xaml/map" 
    x:Class="DetectVisibleItems.MainWindow"
    Title="MainWindow" Height="800" Width="1000">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="3*"/>
            <ColumnDefinition Width="1*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="7*"/>
            <RowDefinition Height="1*"/>
        </Grid.RowDefinitions>

        <dxm:MapControl x:Name="mapControl1" Grid.Column="0" Grid.RowSpan="2">
            <dxm:VectorLayer ViewportChanged="VectorLayer_ViewportChanged">
                <dxm:MapItemStorage/>
            </dxm:VectorLayer>
        </dxm:MapControl>
        <dxe:ListBoxEdit x:Name="listBox" Grid.Column="1" SelectedIndexChanged="listBox_SelectedIndexChanged"/>
        <dxe:TextEdit x:Name="textEdit" Grid.Column="1" Grid.Row="1"/>
    </Grid>
</dx:ThemedWindow>
csharp
using DevExpress.Map;
using DevExpress.Xpf.Core;
using DevExpress.Xpf.Map;
using System.Collections.Generic;
using System.Linq;

namespace DetectVisibleItems {
    public partial class MainWindow : ThemedWindow {
        VectorLayer Layer { get { return (VectorLayer)mapControl1.Layers[0]; } }
        MapItemStorage Data { get { return (MapItemStorage)Layer.Data; } }
        public MainWindow() {
            InitializeComponent();
            Data.Items.AddRange(CreateItems());
            UpdateVisibleItemsList(new GeoPoint(90, -180), new GeoPoint(-90, 180));
        }
        static bool IsPointInside(CoordPoint point, CoordPoint topLeft, CoordPoint bottomRight) {
            return (point.GetY() >= bottomRight.GetY()) && (point.GetY() <= topLeft.GetY()) &&
                   (point.GetX() >= topLeft.GetX()) && (point.GetX() <= bottomRight.GetX());
        }
        static List<MapDot> CreateItems() {
            List<MapDot> result = new List<MapDot>();
            for (double lat = -80; lat <= 80; lat += 20)
                for (double lon = -180; lon <= 180; lon += 20)
                    result.Add(new MapDot() { Location = new GeoPoint(lat, lon), Size = 15 });
            return result;
        }
        void UpdateVisibleItemsList(CoordPoint topLeft, CoordPoint bottomRight) {
            IEnumerable<CoordPoint> visibleItems = Data.Items.Select(item => ((MapDot)item).Location).
                                                              Where(location => IsPointInside(location, topLeft, bottomRight));
            listBox.Items.Clear();
            listBox.Items.AddRange(visibleItems.ToArray());
            textEdit.Text = $"Item Count: {listBox.Items.Count}";
        }

        private void VectorLayer_ViewportChanged(object sender, ViewportChangedEventArgs e) {
            if (!e.IsAnimated)
                UpdateVisibleItemsList(e.TopLeft, e.BottomRight); }

        private void listBox_SelectedIndexChanged(object sender, System.Windows.RoutedEventArgs e) {
            if (Layer.SelectedItems.Count != 0) Layer.SelectedItems.Clear();
            if (listBox.SelectedIndex >= 0) {
                Layer.SelectedItems.Add(Data.Items[listBox.SelectedIndex]);
            }
        }
    }
}
vb
Imports DevExpress.Map
Imports DevExpress.Xpf.Core
Imports DevExpress.Xpf.Map
Imports System.Collections.Generic
Imports System.Linq

Namespace DetectVisibleItems
    Public Partial Class MainWindow
        Inherits ThemedWindow

        Private ReadOnly Property Layer As VectorLayer
            Get
                Return CType(mapControl1.Layers(0), VectorLayer)
            End Get
        End Property

        Private ReadOnly Property Data As MapItemStorage
            Get
                Return CType(Layer.Data, MapItemStorage)
            End Get
        End Property

        Public Sub New()
            InitializeComponent()
            Data.Items.AddRange(CreateItems())
            UpdateVisibleItemsList(New GeoPoint(90, -180), New GeoPoint(-90, 180))
        End Sub

        Private Shared Function IsPointInside(ByVal point As CoordPoint, ByVal topLeft As CoordPoint, ByVal bottomRight As CoordPoint) As Boolean
            Return (point.GetY() >= bottomRight.GetY()) AndAlso (point.GetY() <= topLeft.GetY()) AndAlso (point.GetX() >= topLeft.GetX()) AndAlso (point.GetX() <= bottomRight.GetX())
        End Function

        Private Shared Function CreateItems() As List(Of MapDot)
            Dim result As List(Of MapDot) = New List(Of MapDot)()

            For lat As Double = -80 To 80 Step 20

                For lon As Double = -180 To 180 Step 20
                    result.Add(New MapDot() With {
                        .Location = New GeoPoint(lat, lon),
                        .Size = 15
                    })
                Next
            Next

            Return result
        End Function

        Private Sub UpdateVisibleItemsList(ByVal topLeft As CoordPoint, ByVal bottomRight As CoordPoint)
            Dim visibleItems As IEnumerable(Of CoordPoint) = Data.Items.[Select](Function(item) CType(item, MapDot).Location).Where(Function(location) IsPointInside(location, topLeft, bottomRight))
            listBox.Items.Clear()
            listBox.Items.AddRange(visibleItems.ToArray())
            textEdit.Text = $"Item Count: {listBox.Items.Count}"
        End Sub

        Private Sub VectorLayer_ViewportChanged(ByVal sender As Object, ByVal e As ViewportChangedEventArgs)
            If Not e.IsAnimated Then UpdateVisibleItemsList(e.TopLeft, e.BottomRight)
        End Sub

        Private Sub listBox_SelectedIndexChanged(ByVal sender As Object, ByVal e As Windows.RoutedEventArgs)
            If Layer.SelectedItems.Count <> 0 Then Layer.SelectedItems.Clear()

            If listBox.SelectedIndex >= 0 Then
                Layer.SelectedItems.Add(Data.Items(listBox.SelectedIndex))
            End If
        End Sub
    End Class
End Namespace

See Also

LayerBase Class

LayerBase Members

DevExpress.Xpf.Map Namespace