This sample demonstrates how to create a graphics layer by binding to a source of items that reference location using X and Y values. The PointDataSource property references an ObservableCollection of objects with properties containing X and Y values. The PointDataSource.XCoordinateBinding is set to the property containing X values, and the PointDataSource.YCoordinateBinding is set to the property containing Y values. The appropriate event mechanisms are in place so changes in the items are reflected in the graphics layer. This sample highlights how the functionality can be used in the Model View ViewModel (MVVM) design pattern.
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Controls;
using System.Windows.Input;
namespace ArcGISWPFSDK
{
publicpartialclass UsingPointDataSource : UserControl
{
public UsingPointDataSource()
{
InitializeComponent();
}
}
publicclass MainModel : INotifyPropertyChanged
{
private ObservableCollection<DataPoint> _PointsOfInterest;
public ObservableCollection<DataPoint> PointsOfInterest
{
get { return _PointsOfInterest; }
set
{
if (_PointsOfInterest != value)
{
_PointsOfInterest = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("PointsOfInterest"));
}
}
}
publicevent PropertyChangedEventHandler PropertyChanged;
}
publicclass DataPoint : INotifyPropertyChanged
{
privatedouble _X;
privatedouble _Y;
privatebool _IsSelected;
publicdouble X
{
get { return _X; }
set
{
if (_X != value)
{
_X = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("X"));
}
}
}
publicdouble Y
{
get { return _Y; }
set
{
if (_Y != value)
{
_Y = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Y"));
}
}
}
publicstring _Name;
publicstring Name
{
get { return _Name; }
set
{
if (_Name != value)
{
_Name = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
}
publicbool IsSelected
{
get { return _IsSelected; }
set
{
if (_IsSelected != value)
{
_IsSelected = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("IsSelected"));
}
}
}
publicevent PropertyChangedEventHandler PropertyChanged;
}
publicclass MainViewModel
{
privateconstdouble width = 360;
privateconstdouble height = 180;
privatestatic Random r = new Random();
public MainModel Data { get; set; }
privatestatic MainViewModel instance;
public MainViewModel Instance
{
get
{
if (instance == null)
instance = new MainViewModel();
return instance;
}
}
public ICommand Randomize { get; privateset; }
public ICommand AddRandom { get; privateset; }
public ICommand RemoveFirst { get; privateset; }
public MainViewModel()
{
Data = new MainModel()
{
PointsOfInterest = new
System.Collections.ObjectModel.ObservableCollection<DataPoint>()
};
GenerateDataSet();
AddRandom = new DelegateCommand((a) => AddRandomEntry(), (b) => { returntrue; });
RemoveFirst = new DelegateCommand((a) =>
{
if (Data.PointsOfInterest.Count > 0) Data.PointsOfInterest.RemoveAt(0);
}, (b) => { returntrue; });
Randomize = new DelegateCommand((a) => RandomizeEntries(), (b) => { returntrue; });
}
#region Generate random data
privatevoid GenerateDataSet()
{
for (int i = 0; i < 10; i++)
{
AddRandomEntry();
}
}
privatevoid AddRandomEntry()
{
Data.PointsOfInterest.Add(CreateRandomEntry(Data.PointsOfInterest.Count));
}
private DataPoint CreateRandomEntry(int i)
{
returnnew DataPoint()
{
X = r.NextDouble() * width - width * .5,
Y = r.NextDouble() * height - height * .5,
Name = string.Format("Item #{0}", i)
};
}
privatevoid RandomizeEntries()
{
for (int i = 0; i < Data.PointsOfInterest.Count; i++)
{
var pnt = Data.PointsOfInterest[r.Next(Data.PointsOfInterest.Count)];
pnt.X = r.NextDouble() * width - width * .5;
pnt.Y = r.NextDouble() * height - height * .5;
}
}
#endregion
}
publicclass DelegateCommand : ICommand
{
Func<object, bool> canExecute;
Action<object> executeAction;
bool canExecuteCache;
public DelegateCommand(Action<object> executeAction, Func<object, bool> canExecute)
{
this.executeAction = executeAction;
this.canExecute = canExecute;
}
publicbool CanExecute(object parameter)
{
bool temp = canExecute(parameter);
if (canExecuteCache != temp)
{
canExecuteCache = temp;
if (CanExecuteChanged != null)
{
CanExecuteChanged(this, new EventArgs());
}
}
return canExecuteCache;
}
publicevent EventHandler CanExecuteChanged;
publicvoid Execute(object parameter)
{
executeAction(parameter);
}
}
}
Imports System
Imports System.Windows.Controls
Imports System.Windows.Input
Imports System.ComponentModel
Imports System.Collections.ObjectModel
Namespace ArcGISWPFSDK
PartialPublicClass UsingPointDataSource
Inherits UserControl
PublicSubNew()
InitializeComponent()
EndSubEndClassPublicClass MainModel
Implements INotifyPropertyChanged
Private _PointsOfInterest As ObservableCollection(Of DataPoint)
PublicProperty PointsOfInterest() As ObservableCollection(Of DataPoint)
GetReturn _PointsOfInterest
EndGetSet(ByVal value As ObservableCollection(Of DataPoint))
If _PointsOfInterest IsNot value Then
_PointsOfInterest = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("PointsOfInterest"))
EndIfEndSetEndPropertyPublicEvent PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
EndClassPublicClass DataPoint
Implements INotifyPropertyChanged
Private _X AsDoublePrivate _Y AsDoublePrivate _IsSelected AsBooleanPublicProperty X() AsDoubleGetReturn _X
EndGetSet(ByVal value AsDouble)
If _X <> value Then
_X = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("X"))
EndIfEndSetEndPropertyPublicProperty Y() AsDoubleGetReturn _Y
EndGetSet(ByVal value AsDouble)
If _Y <> value Then
_Y = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Y"))
EndIfEndSetEndPropertyPublic _Name AsStringPublicProperty Name() AsStringGetReturn _Name
EndGetSet(ByVal value AsString)
If _Name <> value Then
_Name = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Name"))
EndIfEndSetEndPropertyPublicProperty IsSelected() AsBooleanGetReturn _IsSelected
EndGetSet(ByVal value AsBoolean)
If _IsSelected <> value Then
_IsSelected = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("IsSelected"))
EndIfEndSetEndPropertyPublicEvent PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
EndClassPublicClass MainViewModel
PrivateConst width AsDouble = 360
PrivateConst height AsDouble = 180
PrivateShared r AsNew Random()
PublicProperty Data() As MainModel
PrivateShared mvm_instance As MainViewModel
PublicReadOnlyProperty Instance() As MainViewModel
GetIf mvm_instance IsNothingThen
mvm_instance = New MainViewModel()
EndIfReturn mvm_instance
EndGetEndPropertyPrivate privateRandomize As ICommand
PublicProperty Randomize() As ICommand
GetReturn privateRandomize
EndGetPrivateSet(ByVal value As ICommand)
privateRandomize = value
EndSetEndPropertyPrivate privateAddRandom As ICommand
PublicProperty AddRandom() As ICommand
GetReturn privateAddRandom
EndGetPrivateSet(ByVal value As ICommand)
privateAddRandom = value
EndSetEndPropertyPrivate privateRemoveFirst As ICommand
PublicProperty RemoveFirst() As ICommand
GetReturn privateRemoveFirst
EndGetPrivateSet(ByVal value As ICommand)
privateRemoveFirst = value
EndSetEndPropertyPublicSubNew()
Data = New MainModel() With
{
.PointsOfInterest = New System.Collections.ObjectModel.ObservableCollection(Of DataPoint)()
}
GenerateDataSet()
AddRandom = New DelegateCommand(Sub(a) AddRandomEntry(), Function(b)
ReturnTrueEndFunction)
RemoveFirst = New DelegateCommand(Sub(a)
If Data.PointsOfInterest.Count > 0 Then
Data.PointsOfInterest.RemoveAt(0)
EndIfEndSub, Function(b) True)
Randomize = New DelegateCommand(Sub(a) RandomizeEntries(), Function(b)
ReturnTrueEndFunction)
EndSub#Region"Generate random data "PrivateSub GenerateDataSet()
For i AsInteger = 0 To 9
AddRandomEntry()
Next i
EndSubPrivateSub AddRandomEntry()
Data.PointsOfInterest.Add(CreateRandomEntry(Data.PointsOfInterest.Count))
EndSubPrivateFunction CreateRandomEntry(ByVal i AsInteger) As DataPoint
ReturnNew DataPoint() With {.X = r.NextDouble() * width - width * 0.5, .Y = r.NextDouble() * height - height * 0.5, .Name = String.Format("Item #{0}", i)}
EndFunctionPrivateSub RandomizeEntries()
For i AsInteger = 0 To Data.PointsOfInterest.Count - 1
Dim pnt = Data.PointsOfInterest(r.Next(Data.PointsOfInterest.Count))
pnt.X = r.NextDouble() * width - width * 0.5
pnt.Y = r.NextDouble() * height - height * 0.5
Next i
EndSub#End RegionEndClassPublicClass DelegateCommand
Implements ICommand
Dim can_Execute As Func(Of Object, Boolean)
Dim executeAction As Action(Of Object)
Dim canExecuteCache AsBooleanPublicSubNew(ByVal executeAction As Action(Of Object), ByVal canExecute As Func(Of Object, Boolean))
Me.executeAction = executeAction
Me.can_Execute = canExecute
EndSubPublicFunction CanExecute(ByVal parameter AsObject) AsBooleanImplements System.Windows.Input.ICommand.CanExecute
Dim temp AsBoolean = can_Execute(parameter)
If canExecuteCache <> temp Then
canExecuteCache = temp
IfNot CanExecuteChangedEvent IsNothingThenRaiseEvent CanExecuteChanged(Me, New EventArgs())
EndIfEndIfReturn canExecuteCache
EndFunctionPublicEvent CanExecuteChanged(sender AsObject, e As System.EventArgs) Implements System.Windows.Input.ICommand.CanExecuteChanged
PublicSub Execute(parameter AsObject) Implements System.Windows.Input.ICommand.Execute
executeAction(parameter)
EndSubEndClassEndNamespace