0

I am creating a Map control/framework library. I have a main Map control which can contain a number of LayerControls. I planned to make those LayerControls to inherit from ItemsControl to allow user use ItemTemplate to define various objects with binding to ViewModels to appear on the map like charts, pins, ships, etc.

Here is an example usage:

<map:Map
    Scale="{Binding Path=Scale}"
    CenterLocation="{Binding Path=CenterLocation}"
    MapParametersChangedCommand="{Binding Path=MapParametersChangedCommand}"
    MouseDoubleClickCommand="{Binding Path=ChartObjectInfoRequestedCommand}"
    UseWaitCursorIcon="{Binding Path=UseWaitCursorIcon}"
    >
    <map:Map.Layers>
        <layers:GeoImageLayer ItemsSource="{Binding Path=WmsLayerViewModel.WmsMaps}">
            <layers:GeoImageLayer.ItemTemplate>
                <DataTemplate DataType="{x:Type viewModels:WmsMapViewModel}">
                    <map:GeoImage
                        Source="{Binding Path=ImageSource}"
                        ImageOffset="{Binding Path=ImageTransform}"
                        />
                </DataTemplate>
            </layers:GeoImageLayer.ItemTemplate>
        </layers:GeoImageLayer>
    </map:Map.Layers>
</map:Map>

Now my problem: When a map specific control (image, pin, ship, etc) is created from ItemTemplate I need to access it to subscribe them to some map specific events and later on to unsubscribe on their removal. I want all of this to be handled internally without the need of using ViewModels to handle it. In one of the questions asked here on SO someone suggested this solution:

protected abstract class BaseGeoLayer : ItemsControl
{    
    protected BaseGeoLayer()
    {
        ((INotifyCollectionChanged) Items).CollectionChanged += OnCollectionChanged;
    }
    
    private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        // doing stuff
    }
}

But CollectionChanged event gives the bound ViewModels, not the controls. Also I have to take into consideration possibility to iterate over those child controls during runtime.

Is there an easy way to achieve this without using VisualTreeHelper?

Ganther
  • 5
  • 2
  • Have you tried to navigate through the "Controls" property of the Sender, or the "Parent", depending on the situation? – Carles Oct 08 '20 at 10:07
  • The sender is the Items property of ItemsControl. It has neither Controls nor Parent properties. – Ganther Oct 08 '20 at 10:20
  • Are the map specific events almost the same for every type of object you are going to place on the map? If so, you might consider implementing a behavior who let you attached/detach those event to an AbstractViewModel that should be the base class for every ViewModel Binded to the objects placed on the map. – trix Oct 08 '20 at 10:45
  • Does this answer your question? [How do I access the children of an ItemsControl?](https://stackoverflow.com/questions/1000345/how-do-i-access-the-children-of-an-itemscontrol) – nalka Oct 08 '20 at 11:41
  • @nalka Nope, the solution provides a ContentPresenter which contains the control I am looking for. But I can't find a way of accessing it. – Ganther Oct 08 '20 at 12:04
  • Have you tried [`ItemContainerGenerator.ItemsChanged`](https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.itemcontainergenerator.itemschanged)? – nalka Oct 08 '20 at 12:10

1 Answers1

0

I managed to get the created/removed control by adding a bubbling RoutedEvent which is fired by the control's Loaded/Unloaded events.

Ganther
  • 5
  • 2