Solved! Go to Solution.
public class DataContextProxy : Freezable { #region Overrides of Freezable protected override Freezable CreateInstanceCore() { return new DataContextProxy(); } #endregion public object Data { get { return (object)GetValue(DataProperty); } set { SetValue(DataProperty, value); } } public static readonly DependencyProperty DataProperty = DependencyProperty.Register("Data", typeof(object), typeof(DataContextProxy), new UIPropertyMetadata(null)); }
<esri:Map> <esri:Map.Resources> <local:DataContextProxy x:Key="proxy" Data="{Binding}" /> </esri:Map.Resources> <esri:ArcGISTiledMapServiceLayer ID="PhysicalTiledLayer" Url="http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer"/> <esri:GraphicsLayer ID="MyGraphicsLayer" GraphicsSource="{Binding Path=Data.SearchResults, Source={StaticResource proxy}}" Renderer="{StaticResource MySimpleRenderer}" /> </esri:Map>
<esri:Map IsLogoVisible="False" x:Name="MapObject" Grid.Row="1"> <Mapping:LocalOpenStreetMapLayer Style="Mapnik" /> <Controls:AutoGpsLayer x:Name="AutoGpsLayer" Bearing="{Binding Bearing,Mode=OneWay}" /> </esri:Map>
public double Bearing { get { return _bearing; } set { _bearing = value; NotifyOfPropertyChange(()=>Bearing);} }
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Bearing; DataItem=null; target element is 'AutoGpsLayer' (HashCode=22325283); target property is 'Bearing' (type 'Double')
<Window.Resources> <local:MainViewModel x:Key="MainViewModel" /> </Window.Resources> <Grid DataContext="{StaticResource MainViewModel}"> <esri:Map Extent="-14268281.1311858,2195120.17402859,-7232639.54776086,7467160.93387503"> <esri:ArcGISTiledMapServiceLayer Url="http://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer" /> <esri:GraphicsLayer ID="MyGraphicsLayer" GraphicsSource="{Binding SearchResults, Source={StaticResource MainViewModel}}"/> </esri:Map> </Grid>
public class DataContextProxy : Freezable { #region Overrides of Freezable protected override Freezable CreateInstanceCore() { return new DataContextProxy(); } #endregion public object Data { get { return (object)GetValue(DataProperty); } set { SetValue(DataProperty, value); } } public static readonly DependencyProperty DataProperty = DependencyProperty.Register("Data", typeof(object), typeof(DataContextProxy), new UIPropertyMetadata(null)); }
<esri:Map> <esri:Map.Resources> <local:DataContextProxy x:Key="proxy" Data="{Binding}" /> </esri:Map.Resources> <esri:ArcGISTiledMapServiceLayer ID="PhysicalTiledLayer" Url="http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer"/> <esri:GraphicsLayer ID="MyGraphicsLayer" GraphicsSource="{Binding Path=Data.SearchResults, Source={StaticResource proxy}}" Renderer="{StaticResource MySimpleRenderer}" /> </esri:Map>
Sheled,
DependencyObject's don't provide a DataContext, but they can still participate in data binding so they work great in MVVM. The trick is to specify the Source in your binding statement. For a FrameworkElement there is an implicit source (the DataContext) but for a DependencyObject you have to declare it explicitly.
There are different techniques to do this. In the following example, I declare the ViewModel as a resource in the View and then I can use the StaticResource approach:<Window.Resources> <local:MainViewModel x:Key="MainViewModel" /> </Window.Resources> <Grid DataContext="{StaticResource MainViewModel}"> <esri:Map Extent="-14268281.1311858,2195120.17402859,-7232639.54776086,7467160.93387503"> <esri:ArcGISTiledMapServiceLayer Url="http://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer" /> <esri:GraphicsLayer ID="MyGraphicsLayer" GraphicsSource="{Binding SearchResults, Source={StaticResource MainViewModel}}"/> </esri:Map> </Grid>
Hopefully that does the trick for you.
/Jeff
Antti,
I love this solution! Very clean and works like a champ.
Thanks for the tip.
-Jeff
To original poster,
If the post answered to your problem, please mark to answered.
Why use a workaround when you can just utilize the "Binding" keyword and make the platform do all the rest of the work for you?
At my knowledge, the issue here is that you need to explicitly define source for your binding when binding from non-visual elements (layers in this case) to something.
Since layers aren't part of the visual tree, they do not get the DataContext derived from the upper elements so we need to proxy the DataContext somehow to the non-visual elements in XAML.