1

I have a third party usercontrol that I have to use to display a Map, unfortunately this third party control does not support data binding but the framework I have to use it in can only pass data via binding.

Example code:-

As things stand I can add the third party control to a page's XAML file like this:-

<ViewerControl:Viewer x:Name="Viewer"
                      HorizontalAlignment="Stretch"
                      VerticalAlignment="Stretch"
                      MouseMove="OnMouseMove">
</ViewerControl:Viewer>

Then I can define a map layer and add it to the map in the codebehind like this:-

var layerDefinition = new WMSLayerDefinition("AFG_AGS_1M_MFS",
                                             new Extent(59.7812, 26.9152, 75.5985, 40.9476),
                                             "EPSG:4326") { IsSelectable = true };
var wmsLayer = new WMSLayer(Viewer.GetViewController(),
                            layerDefinition,
                            "http://ogc.bgs.ac.uk/cgi-bin/BGS_AGS_EN_Bedrock_and_Structural_Geology/wms/");
Viewer.GetLayerManager().GetLayerGroup(layerGroupName).AddLayer(wmsLayer);

What I would like to be able to do is bind an ObservableCollection of WMSLayer (or my own model that is a little more generic than the one used by the viewer) to the viewer, however as I don't have access to the viewer code I'm assuming that I would need to write a wrapper control.

As far as I can see the wrapper control would need to contain an instance of the third party usercontrol and a DependencyProperty to allow me to bind a ObservableCollection of Map Layer data so that I can use it as the parameters for the methods on the third party usercontrol.

I have read so many examples of binding in custom usercontrols that my head is spinning, unfortunately they all deal with presenting the bound data in the UI. What I want to do is pass the bound data on to another control that will take care of the presentation, I know that this is not really the correct way for Silverlight controls to work but as I have no influence over the design of the third party usercontrol I can't see any other way around this.

Can anyone help me to understand how I can access the bound data in my wrapper usercontrol and pass it into the methods exposed by the third party usercontrol please?

Thanks in advance :o)

Mike
  • 11
  • 2

1 Answers1

0

This answer is somewhat dependent on who owns the ObservableCollection, but should be malleable enough to meet your needs.

A simple solution is to hook up to the INotifyCollectionChanged interface provided by the ObservableCollection:

// FrameworkElement.DataContextChanged (Window/Page/UserControl/etc)
private void OnDataContextChanged(object sender,
    DependencyPropertyChangedEventArgs e)
{
    // if your DataContext is some other type, do the appropriate casting
    var oldValue = e.OldValue as ObservableCollection<YourLayer>();
    if (oldValue != null)
    {
         oldValue.CollectionChanged -= LayerCollectionChanged;
    }

    var newValue = e.NewValue as ObservableCollection<YourLayer>();
    if (newValue != null)
    {
         newValue.CollectionChanged += LayerCollectionChanged;
    }
}

Once you've established the connection in an appropriate handler, you just listen for modifications and manually handle the adding/removing from your layer manager:

private void LayerCollectionChanged(object sender,
    NotifyCollectionChangedEventArgs e)
{
    switch (e.Action)
    {
    case NotifyCollectionChangedAction.Add:
        foreach (YourLayer layer in e.NewItems)
        {
            // custom method to handle conversion from YourLayer to WMSLayer
            this.AddLayer(layer);
        }
        break;

    case NotifyCollectionChangedAction.Remove:
        foreach (YourLayer layer in e.OldItems)
        {
            // custom method to remove a WMSLayer matching the YourLayer
            this.RemoveLayer(layer);
        }
        break;

     // handle the other notifications as you see fit
    }
}
user7116
  • 63,008
  • 17
  • 141
  • 172
  • Thanks, I've tried something similar for a `DependencyProperty` before but not for the `DataContext`. having added your code I don't seem to be able to wire up your `OnDataContextChanged` to an event in the constructor. – Mike Nov 28 '11 at 17:33
  • The constructor of what exactly? – user7116 Nov 28 '11 at 18:42
  • I guess what I'm asking is what should be calling `OnDataContextChanged` or what event should it be assigned to because there doesn't seems to be a `DataContextChanged` event on the `UserControl` that I can assign this handler to. – Mike Nov 29 '11 at 13:01
  • I want to understand what you suggested for educational purposes. I've solved the original problem using a `DependencyProperty` and also using the advice given [here](http://stackoverflow.com/questions/901921/observablecollection-and-item-propertychanged) I've been able to also listen for changes to the properties of the items in my `ObservableCollection`. Thanks for your help, I'll post details of the solution I've employed once I've tidied it up a bit. – Mike Nov 29 '11 at 13:02
  • Ah, once again bit by reading the WPF MSDN instead of SL4. You were right to use a `DependencyProperty`, however, you shouldn't need to wire up the items `PropertyChanged` to the `ObservableCollection`. You can use the `DependencyProperty`'s Changed event instead of the `DataContextChanged` to provide the wiring that I've shown. – user7116 Nov 29 '11 at 14:20