2011-05-04 6 views
8

Tengo una aplicación WPF, y el diseño sigue el modelo MVVM estándar.Los controles de datos no deberían actualizarse si no están visibles

Cuando los datos subyacentes cambian, mi modelo de vista activa el evento PropertyChanged para que los controles puedan actualizarse.

Mi vista principal es un control de pestañas, por lo que la mayoría de los controles son invisibles en cualquier momento. Hay problemas de rendimiento, y me he dado cuenta de que gran parte del tiempo de la CPU está dedicado a buscar datos para actualizar los controles invisibles. (Mi modelo de vista utiliza evaluación diferida, por lo que activa los eventos PropertyChanged, pero no calcula las propiedades finales que se pueden visualizar hasta que se lo solicite).

¿WPF tiene una forma estándar de resolver este problema?

Idealmente, si un control invisible recibe un evento PropertyChanged relevante, debería simplemente pensar "Debo volver a consultar esa propiedad cuando vuelva a estar visible".

+0

No creo que exista, sería bastante útil sin embargo. –

Respuesta

1

No creo que haya ninguna infraestructura para manejar los enlaces de desactivación asociados con controles no visibles. Desafortunadamente, hay muchas situaciones en las que desearía un control que no sea visible para participar en el enlace de datos. Lo más importante, a menudo tiene un control cuya visibilidad depende de un enlace. Además, puede tener un enlace entre las propiedades de un control visible y un control no visible. O alguien puede querer exactamente lo contrario de lo que quiere: el control se rellena a sí mismo mientras no es visible y luego salta completamente poblado una vez visible.

Creo que la única buena solución para su situación es evitar controles pesados ​​no visibles, si eso es posible. Específicamente para su control de pestañas, habría pensado que sería el comportamiento predeterminado, pero tal vez dependa de su situación. Irónicamente, algunas personas se quejan de que el TabControl destruye a sus hijos al cambiar entre pestañas y les gustaría saber cómo evitarlo, ya que mantener todas las pestañas de fondo en la memoria requiere algo de trabajo. Pero parece que tienes el problema opuesto.

Para referencia, aquí es la fuente que he mencionado para TabControl hijos:

Usted puede ser capaz de hacer algunos experimentos en un pequeño proyecto para "encender" el comportamiento de reciclaje Ellos están tratando de apagar. Si su control se cargó a pedido, el cambio de pestaña podría ser un poco más lento, pero el rendimiento en una pestaña mejoraría.

+0

Por razones heredadas, en realidad se trata de un control de pestañas WinForms, con varias pestañas con controles WPF a través de ElementHost. Mi problema puede no ser representativo del comportamiento de control de pestañas habitual. –

+0

Además, gracias por proporcionar un excelente contraargumento a la premisa del título. (Estoy experimentando con títulos polémicos para ver si obtienen más lecturas :-). –

+0

Interesante pregunta. Espero que encuentres una solución. En mi caso tu estrategia funcionó. :-) –

1

Hicimos algo en este sentido en nuestra base de modelo de vista ..

Nota, hay que congelar/descongelar corresponde con la visibilidad de la vista.

Básicamente atrapa todos los eventos PropertyChanged mientras está congelado, y los saca cuando se descongela. Mientras que también no guardamos a los engañados, ya que no importan en nuestro caso.

public abstract class ViewModelBase : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    private readonly HashSet<string> hashSet = new HashSet<string>(); 
    private bool isFrozen; 

    protected void RaisePropertyChanged(string propertyName) 
    { 
     if (isFrozen) 
     { 
      lock (hashSet) 
      { 
       hashSet.Add(propertyName); 
       return; 
      } 
     } 

     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    protected void Freeze() 
    { 
     isFrozen = true; 
    } 

    /// <summary> 
    /// Enable PropertyChanged Events to fire again 
    /// </summary> 
    protected void Thaw(bool fireQueued) 
    { 
     isFrozen = false; 
     if (fireQueued) 
     { 
      lock (hashSet) 
      { 
       PropertyChangedEventHandler handler = PropertyChanged; 
       if (handler != null) 
       { 
        foreach (string propertyName in hashSet) 
        { 
         handler(this, new PropertyChangedEventArgs(propertyName)); 
        } 
       } 

       hashSet.Clear(); 
      } 
     } 
     else 
     { 
      hashSet.Clear(); 
     } 
    } 
} 
0

Mi modelo de vista base tiene una propiedad IsVisible. Cuando el modelo de vista es invisible simplemente suprima las notificaciones de propiedad cambiada. Cuando se vuelve visible, se activa un evento cambiado propiedad para cada propiedad (pr pass en nulo para el nombre de la propiedad)

Cuestiones relacionadas