在双向绑定中将依赖项 属性 值写回视图模型

Writing back a dependency property value to the view model in two-way binding

我正在实现一个 wpf 控件,它在 Web 浏览器中提供 xaml 和 Google 地图 运行ning 之间的一些通用绑定。目前,绑定是单向的,并且工作正常。

接下来我需要做的是在指定双向绑定时将一个值写回视图模型。我开始使用的 属性 是 Google 地图的缩放。当它在浏览器中更改时,我可以在页面上使用 运行 js 使用新的缩放级别回调我的 C# 代码。

向 DP 提供此新值的正确方法是什么,以便在选择双向绑定时更新视图模型的缩放级别?

我当前的缩放级别 DP 代码:

#region ZoomProperty

    //Called from the web page
    private JSValue MapZoom_OnMapZoomChanged(JSValue[] arguments) {
        string zoom = arguments[0];

        //where do I set the zoom so that the view model bound property is updated?
        return null;
    }

public static readonly DependencyProperty ZoomProperty =
    DependencyProperty.Register("Zoom", typeof(string), typeof(GoogleMap), new FrameworkPropertyMetadata(string.Empty, OnZoomPropertyChanged), OnZoomPropertyValidate);

public string Zoom {
    get { return (string)GetValue(ZoomProperty); }
    set { SetValue(ZoomProperty, value); }
}

private static bool OnZoomPropertyValidate(object value) {
    return value is string;
}

private static void OnZoomPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) {
    GoogleMap control = source as GoogleMap;
    control.SetZoom(e.NewValue.ToString());
}

private string zoom;
public void SetZoom(string value) {
    if (!googleMapPageReady) {
        zoom = value;
        return;
    }

    webControl.ExecuteJavascript(string.Format("setZoom({0})", zoom));
}

#endregion

除非我忽略了什么,否则你只需要做:

private JSValue MapZoom_OnMapZoomChanged(JSValue[] arguments)
{
    string newZoom= arguments[0];
    this.Zoom = newZoom; // here
    return null;
}

依赖性 属性 模式已设置,因此从外部您可以将 Zoom 视为普通的 c# 属性(setter 和 getter)。如果你查看那个 属性 的 setter 它调用 SetValue(), which is on the DependencyObject base class and does the magic to notify the binding engine of the change (also see: Register())

更新

当地图是第一个提供更改的地图时,防止更改将更新发送到地图的简单方法:

private bool IsMapUpdateSuppressed = false;

private JSValue MapZoom_OnMapZoomChanged(JSValue[] arguments)
{
    string newZoom= arguments[0];
    this.IsMapUpdateSuppressed = true;
    this.Zoom = newZoom;
    this.IsMapUpdateSuppressed = false;
    return null;
}

private static void OnZoomPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
    GoogleMap control = source as GoogleMap;
    if (!control.IsMapUpdateSuppressed)
    {
        control.SetZoom(e.NewValue.ToString());
    }
}

这允许 DP 值像往常一样更改、处理和通知绑定引擎,但只是阻止调用 SetZoom