2010-09-02 57 views
5

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

但是,如果我点击一个结果链接,然后单击返回按钮返回到结果列表,我的所有CheckBox.IsChecked数据绑定都被打破。其他数据绑定控件(组合框,DatePickers等)继续按预期工作。绑定到CheckBox控件上的其他属性,如IsEnabled,可以正常工作。但IsChecked绑定仍然中断,直到我刷新页面。

下面是用于我的CheckBox控件之一的XAML:

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

正如你所看到的,没有什么花哨回事。但是,在WPF应用向前或向后导航到页面之后,IsChecked绑定将被破坏,而IsEnabled属性将继续工作。

这是怎么回事?这是一个错误?

更新:在玩过一些替代品后,我发现这个问题也影响了CheckBox派生自的ToggleButton控件。

UPDATE2:它也被破坏为TextBox.Text属性。

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

回答

5

显然,它的一个错误。以下是Microsoft Connect上的错误报告: Binding does not work after back/forward navigation

谁报告的错误的,RQDQ,也提到他的方法来处理这个问题的用户:

我已经找到了解决方法是手动调用BindingOperations.SetBinding用于在页面中所有绑定加载事件。无论是明确导航还是通过历史记录(后退/前进操作),这似乎都有效。

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

我希望微软很快修复这个问题。这对于导航风格的WPF应用程序来说是一个严重的问题。

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。

+0

这里最大的问题是它可能很快导致内存泄漏。 – ouflak 2014-08-21 16:38:26