2010-09-02 22 views
5

Tengo una página dentro de una aplicación de estilo de navegación WPF que muestra resultados de búsqueda. La página contiene varios controles vinculados a datos. La página en sí funciona bien; realiza la búsqueda y devuelve los resultados. Los controles CheckBox enlazados a datos funcionan correctamente.WPF Enlace de datos MVVM roto después de la navegación de la página

Pero si hago clic en un enlace de resultado y luego hago clic en el botón Atrás para volver a la lista de resultados, todos mis enlaces de datos CheckBox.IsChecked están rotos. Otros controles vinculados a datos (ComboBoxes, DatePickers, etc.) continúan funcionando como se esperaba. La vinculación a otras propiedades en el control CheckBox, como IsEnabled, funciona correctamente. Pero el enlace IsChecked permanece roto hasta que actualizo la página.

Aquí está el XAML usado para uno de mis controles CheckBox:

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

Como se puede ver, no hay nada de fantasía pasando aquí. Pero después de navegar la aplicación WPF hacia adelante o hacia atrás a la página, el enlace IsChecked se romperá mientras la propiedad IsEnabled continuará funcionando.

¿Qué está pasando aquí? ¿Es esto un error?

ACTUALIZACIÓN: Después de jugar con algunas alternativas, descubrí que este problema también afecta al control ToggleButton, del cual se deriva CheckBox.

UPDATE2: Y también está roto para la propiedad TextBox.Text.

¿Hay alguna forma de "actualizar" los enlaces de datos para estos controles? ¿O debería tomar algún otro enfoque para solucionar este problema?

Respuesta

5

Aparentemente, es es un error. Aquí está el informe de error en Microsoft Connect: Binding does not work after back/forward navigation.

El usuario que informó del fallo, RQDQ, también mencionó su enfoque para abordar el problema:

La solución que he encontrado es llamar manualmente BindingOperations.SetBinding para todos los enlaces en la página durante la Evento cargado Esto parece funcionar ya sea navegando de forma explícita o vía historial (operaciones hacia atrás/adelante).

Esto es solo un problema en WPF4. El enlace de datos funciona como se espera en .NET 3.5.

Espero que Microsoft solucione esto rápidamente. Este es un problema serio para las aplicaciones WPF de estilo de navegación.

0

Una solución simple es establecer KeepAlive en true y luego para garantizar que no haya problemas con el VIewModel que tenga un estado incorrecto de una carga de página anterior, DataContext se establece en una nueva instancia cada vez en el evento Loaded (es decir, no enlazar a una instancia de ViewModel en su diccionario Page.Resources, por ejemplo, ya que se mantendrá).

Un enfoque estándar que utilizamos para vincular la página al modelo de vista es con un comportamiento simple asociado a la página.

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

Esto asegura que la página está vinculada de nuevo cada vez que el usuario navega de regreso a la página.Esto también le permite usar su contenedor IOC favorito para crear ViewModel.

+0

El mayor problema aquí es que puede provocar rápidamente una pérdida de memoria. – ouflak

Cuestiones relacionadas