页面导航后WPF MVVM数据绑定中断

时间:2010-09-02 03:04:36

标签: wpf data-binding mvvm navigation

我在WPF导航样式的应用程序中有一个显示搜索结果的页面。该页面包含几个数据绑定控件。页面本身工作正常;它执行搜索并返回结果。数据绑定的CheckBox控件正常工作。

但是,如果我单击结果链接然后单击后退按钮返回结果列表,则所有CheckBox.IsChecked数据绑定都会被破坏。其他数据绑定控件(ComboBoxes,DatePickers等)继续按预期工作。绑定到CheckBox控件上的其他属性,如IsEnabled,可以正常工作。但是在我刷新页面之前,IsChecked绑定仍然存在。

这是用于我的一个CheckBox控件的XAML:

<CheckBox IsChecked="{Binding IncludeNote}" Content="Note" IsEnabled="{Binding IsBusy, Converter={StaticResource boolNot}}" />

正如你所看到的,这里没有什么花哨的东西。但在向前或向后导航到页面后,IsChecked绑定将被破坏,而IsEnabled属性将继续有效。

这里发生了什么?这是一个错误吗?

UPDATE:在玩了一些替代方案之后,我发现这个问题也会影响CheckBox派生的ToggleButton控件。

UPDATE2:而且TextBox.Text属性也被破坏了。

有没有办法“刷新”这些控件的数据绑定?或者我应该采取其他方法来解决此问题?

2 个答案:

答案 0 :(得分:5)

显然, 是一个错误。这是关于Microsoft Connect的错误报告: Binding does not work after back / forward navigation

报告错误的用户RQDQ也提到了他处理问题的方法:

  

我发现的解决方法是在Loaded事件期间为Page中的所有绑定手动调用BindingOperations.SetBinding。无论是显式导航还是通过历史导航(后退/前进操作),这似乎都有效。

这只是WPF4中的一个问题。数据绑定在.NET 3.5中按预期工作。

我希望微软能够迅速解决这个问题。对于导航样式的WPF应用程序来说,这是一个严重的问题。

答案 1 :(得分:0)

一个简单的解决方法是将KeepAlive设置为true,然后确保VIewModel在上一次加载时没有问题,每次在Loaded事件中将DataContext设置为一个新实例(即不绑定您的Page.Resources字典中的ViewModel实例,例如它将被保留)。

我们用于将页面绑定到视图模型的标准方法是将简单的行为附加到页面上。

public sealed class PageViewModelBehavior : Behavior<Page>
{
    public Type DataType { get; set; }

    protected override void OnAttached()
    {
        this.AssociatedObject.KeepAlive = true;
        this.AssociatedObject.Loaded += this.AssociatedObjectLoaded;
        this.AssociatedObject.Unloaded += this.AssociatedObjectUnloaded;
        base.OnAttached();
    }

    protected override void OnDetaching()
    {
        this.AssociatedObject.Unloaded -= this.AssociatedObjectUnloaded;
        this.AssociatedObject.Loaded -= this.AssociatedObjectLoaded;
        base.OnDetaching();
    }

    private void AssociatedObjectLoaded(object sender, RoutedEventArgs e)
    {
        if (this.DataType == null || !typeof(IPageViewModel).IsAssignableFrom(this.DataType))
        {
            throw new InvalidOperationException("PageViewModelBehavior.DataType is not set. Page: " + this.AssociatedObject.GetType().Name);
        }

        this.AssociatedObject.DataContext = Activator.CreateInstance(this.DataType);

        // TODO: Call load on your page view model etc.
    }


    private void AssociatedObjectUnloaded(object sender, RoutedEventArgs e)
    {
        // TODO: Call unload on your page view model etc.

        // Allow the throw-away view model to be GC'd
        this.AssociatedObject.DataContext = null;
    }
}

这确保了每次用户导航回页面时页面都会再次绑定。这也允许您使用您喜欢的IOC容器来创建ViewModel。