绑定UserControl DependencyProperty,Always DefaultValue?

时间:2017-01-27 22:51:48

标签: c# wpf mvvm data-binding

我在CodeBehind中创建了一个带有DependencyProperty的UserControl:

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));
}

UserControl内部是一个Map,它包含原始的标记集合(不是DependencyProperty)。我需要在UserControl之外使它可用于绑定,所以在构造函数的末尾(一旦设置了地图的标记),我将它设置为控件的DependencyProperty:

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

然后,UserControl的用户可以绑定如下:

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

ViewModel中的位置:

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

问题是,ViewModel的MapMarkers属性总是以默认值&#34; null结束。&#34;我尝试在PanelMap_Control和ViewModel属性的setter中的SetValue调用上设置断点。调试器首先命中SetValue(),此时_map.Markers有效(非null)。然后它命中ViewModel的setter,值为null - 并且从不反映我传递给SetValue()的实际有效对象。

我确定我只是遗漏了一些简单的东西,但我不能为我的生活找出为什么SetValue(非null)将后跟 ViewModel.MapMarkers.set(null)......再也不会。

(旁注1:我意识到这个DependencyProperty不能用于TwoWay绑定 - 即我无法在UserControl中更新_map.Markers。没关系,我只需要阅读在外面。)

(旁注2:_map.Markers对象永远不会被更改 - 只有集合中的项目 - 所以将DependencyProperty设置为初始集合应该就足够了。)

1 个答案:

答案 0 :(得分:1)

请参阅以下问题。

OneWayToSource Binding seems broken in .NET 4.0

OneWayToSource binding resetting target value

OneWayToSource最初实际上重置了目标属性(标记)。这是设计的。在上面的链接中有关于此的更多信息。

作为一种解决方法,您可以尝试以编程方式设置绑定:

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" />