J23
J23

Reputation: 3221

Binding A UserControl DependencyProperty, Always DefaultValue?

I've got a UserControl with a DependencyProperty created in its CodeBehind:

public partial class PanelMap_Control : UserControl
{
    public ObservableCollection<GMapMarker> Markers
    {
        get { return (ObservableCollection<GMapMarker>)GetValue(MarkersProperty); }
        set { SetValue(MarkersProperty, value); }
    }
    public static readonly DependencyProperty MarkersProperty = DependencyProperty.Register("Markers", typeof(ObservableCollection<GMapMarker>), typeof(PanelMap_Control), new PropertyMetadata(null));
}

Inside the UserControl is a Map, which contains the original collection of markers (not a DependencyProperty). I need to make this available for binding outside the UserControl, so at the end of the constructor (once the map's Markers are all setup), I set it to the control's DependencyProperty:

    public PanelMap_Control()
    {
        InitializeComponent();
        //...map setup...
        this.Markers = _map.Markers;
    }

Then, users of the UserControl can bind like:

    <local:PanelMap_Control Markers="{Binding Path=MapMarkers, Mode=OneWayToSource}"/>

Where in the ViewModel:

    public ObservableCollection<GMap.NET.WindowsPresentation.GMapMarker> MapMarkers
    {
        private get
        {
            return _mapMarkers; 
        }
        set 
        {
            _mapMarkers = value; 
        }
    }
    private ObservableCollection<GMap.NET.WindowsPresentation.GMapMarker> _mapMarkers;

The problem is, the ViewModel's MapMarkers property always ends up with the default value "null." I tried setting breakpoints on the SetValue call in PanelMap_Control and the ViewModel property's setter. The debugger first hits SetValue(), at which point _map.Markers is valid (non-null). THEN it hits the ViewModel's setter, with a value of null - and never reflects the actual valid object I pass to SetValue().

I'm sure I'm just missing something simple, but I can't for the life of me figure out why SetValue(non-null) would be followed by ViewModel.MapMarkers.set(null)...and never again.

(Side note 1: I realize this DependencyProperty won't work for TwoWay binding - i.e. I can't update _map.Markers in the UserControl. That's fine, I only need to read from it externally.)

(Side note 2: The _map.Markers object will never be changed - only the items in the collection - so setting the DependencyProperty to the initial collection should be sufficient.)

Upvotes: 0

Views: 385

Answers (1)

mm8
mm8

Reputation: 169330

Please refer to the following questions.

OneWayToSource Binding seems broken in .NET 4.0

OneWayToSource binding resetting target value

OneWayToSource does actually reset the target property (Markers) initially. This is by design. There is more information about this on the links above.

As a workaround you could try to set up the binding programmatically:

public MainWindow()
{
    InitializeComponent();
    var vm = new ViewModel();
    DataContext = vm;
    vm.MapMarkers = control.Markers;
    BindingOperations.SetBinding(control, PanelMap_Control.MarkersProperty, new Binding("MapMarkets") { TargetNullValue = control.Markers, FallbackValue = control.Markers });
}

XAML:

<local:PanelMap_Control x:Name="control" />

Upvotes: 1

Related Questions