2010-12-06 11 views
21

Tengo una propiedad adjunta de tipo ObservableCollection en un control. Si agrego o elimino elementos de la colección, la interfaz de usuario no se actualiza. Sin embargo, si reemplazo la colección dentro de una nueva, el ViewModel se actualizará.La propiedad de dependencia ObservableCollection no se actualiza cuando se elimina el elemento en la colección

¿Alguien me puede dar un ejemplo de lo que debo hacer dentro del objeto Dependencia para que pueda manejar los cambios dentro de la colección?

parte del objeto de dependencia se enumeran a continuación:

public class RadCalendarBehavior : DependencyObject 
{ 
private static void OnSpecialDaysChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 
    var calendar = d as RadCalendar; 
    if (e.NewValue != null) 
    { 
    calendar.DayTemplateSelector = new SpecialDaySelector((ObservableCollection<DateTime>)e.NewValue, GetSpecialDayTemplate(d)); 
    } 
} 

public static ObservableCollection<DateTime> GetSpecialDays(DependencyObject obj) 
{ 
    return (ObservableCollection<DateTime>)obj.GetValue(SpecialDaysProperty); 
} 

public static void SetSpecialDays(DependencyObject obj, ObservableCollection<DateTime> value) 
{ 
    obj.SetValue(SpecialDaysProperty, value); 
} 

public static readonly DependencyProperty SpecialDaysProperty = 
    DependencyProperty.RegisterAttached("SpecialDays", typeof(ObservableCollection<DateTime>), typeof(RadCalendarBehavior), new UIPropertyMetadata(null, OnSpecialDaysChanged)); 
} 
} 

entiendo que tengo que registrar que la colección ha cambiado, pero estoy seguro de cómo hacer esto dentro de la propiedad de dependencia

Respuesta

33

Un el cambio dentro de la colección no desencadenará la devolución de llamada OnSpecialDaysChanged, porque el valor de la propiedad de dependencia no ha cambiado. Si tiene que reaccionar para detectar cambios con la colección, es necesario controlar el evento evento CollectionChanged manualmente:

private static void OnSpecialDaysChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 
    var calendar = d as RadCalendar; 

    if (e.OldValue != null) 
    { 
    var coll = (INotifyCollectionChanged)e.OldValue; 
    // Unsubscribe from CollectionChanged on the old collection 
    coll.CollectionChanged -= SpecialDays_CollectionChanged; 
    } 

    if (e.NewValue != null) 
    { 
    var coll = (ObservableCollection<DateTime>)e.NewValue; 
    calendar.DayTemplateSelector = new SpecialDaySelector(coll, GetSpecialDayTemplate(d)); 
    // Subscribe to CollectionChanged on the new collection 
    coll.CollectionChanged += SpecialDays_CollectionChanged; 
    } 
} 

private static void SpecialDays_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
{ 
    // handle CollectionChanged 
} 
+0

Gracias. ¿Es posible obtener una referencia del objeto de dependencia dentro de SpecialDays_CollectionChanged? – GoalMaker

+0

¿Qué objeto de dependencia? ¿Te refieres al RadCalendar? No es fácil ... de todos modos, no estoy seguro de que tenga sentido: ¿y si varias instancias de RadCalendar están ligadas a la misma colección? –

+0

Veo a qué te refieres. Estaba intentando que RadCalendar ya no destacara un día especial si se eliminó de la colección, así que pensé que podría hacer esto creando un nuevo SpecialDaySelector y estableciendo el DayTemplateSelector del control Calendar. – GoalMaker

5

Esto es sólo para añadir a la respuesta de Thomas. En mi código que interactúan con las propiedades de la DependencyObject mediante la creación de un objeto manejador necesitas cigarros, como a continuación:

private static void OnSpecialDaysChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 
    var action = new NotifyCollectionChangedEventHandler(
      (o, args) => 
       { 
        var calendar = d as RadCalendar; 

        if (calendar!= null) 
        { 
         // play with calendar's properties/methods 
        } 
       }); 

    if (e.OldValue != null) 
    { 
     var coll = (INotifyCollectionChanged)e.OldValue; 
     // Unsubscribe from CollectionChanged on the old collection 
     coll.CollectionChanged -= action; 
    } 

    if (e.NewValue != null) 
    { 
     var coll = (ObservableCollection<DateTime>)e.NewValue; 
     // Subscribe to CollectionChanged on the new collection 
     coll.CollectionChanged += action; 
    } 
} 

la esperanza que esto sea útil a alguien.

+0

Esto es útil sí, estoy buscando una forma de acceder al objeto DependencyObject en CollectionChangedEventHandler, y parece que funciona. Me resulta difícil de creer que esta es la única manera sin embargo ... ¿Estamos haciendo algo mal? Tengo un DP ObservableCollection, cuando se le agregan elementos (el evento changechanged se dispara ...), tengo que hacer cosas para el control principal (como agregar subcontroles). Y su solución es la única que encontré para acceder a DependencyObj. Desde esta publicación, ¿has encontrado otra forma? – Sam

2

Si usted tiene una propiedad de tipo colección dependencia de mantener en mente lo siguiente:

Si su propiedad es un tipo de referencia, el valor predeterminado especificado en la dependencia de metadatos propiedad no es un valor predeterminado por ejemplo; en su lugar, es un valor predeterminado que se aplica a todas las instancias del tipo. [...]
Para corregir este problema, debe restablecer el valor de la propiedad de dependencia de la colección a una instancia única, como parte de la llamada del constructor de la clase.

(ver MSDN Collection-Type Dependency Properties)

Para responder a la pregunta de Sam (Yo acabo de encontrar con el mismo problema):

Haga su CollectionChanged-manejador no estático y darse de baja/volver a suscribirse en ejemplo- nivel.

private static void OnSpecialDaysChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 
    var calendar = d as RadCalendar; 

    if (e.OldValue != null) 
    { 
    var coll = (INotifyCollectionChanged)e.OldValue; 
    // Unsubscribe from CollectionChanged on the old collection of the DP-instance (!) 
    coll.CollectionChanged -= d.SpecialDays_CollectionChanged; 
    } 

    if (e.NewValue != null) 
    { 
    var coll = (ObservableCollection<DateTime>)e.NewValue; 
    calendar.DayTemplateSelector = new SpecialDaySelector(coll, GetSpecialDayTemplate(d)); 
    // Subscribe to CollectionChanged on the new collection of the DP-instance (!) 
    coll.CollectionChanged += d.SpecialDays_CollectionChanged; 
    } 
} 

private void SpecialDays_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
{ 
    // handle CollectionChanged on instance-level 
} 
Cuestiones relacionadas