Свойство зависимости ObservableCollection не обновляется при удалении элемента в коллекции - PullRequest
23 голосов
/ 06 декабря 2010

У меня есть прикрепленное свойство типа ObservableCollection для элемента управления.Если я добавляю или удаляю элементы из коллекции, пользовательский интерфейс не обновляется.Однако, если я заменю коллекцию внутри новой ViewModel, пользовательский интерфейс обновит.

Может ли кто-нибудь дать мне пример того, что мне нужно делать в объекте Dependency, чтобы он мог обрабатывать изменения в коллекции?

Часть объекта зависимости указана ниже:

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

Я понимаю, что мне нужно зарегистрировать, что коллекция изменилась, но я не уверен, как это сделать в свойстве зависимости

Ответы [ 3 ]

37 голосов
/ 06 декабря 2010

Изменение в коллекции не вызовет обратный вызов OnSpecialDaysChanged, поскольку значение свойства зависимости не изменилось. Если вам нужно реагировать на обнаружение изменений в коллекции, вам нужно обработать событие CollectionChanged вручную:

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
}
5 голосов
/ 11 августа 2015

Это просто, чтобы добавить к ответу Томаса.В моем коде я взаимодействую со свойствами DependencyObject, создавая объект обработчика локально, как показано ниже:

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

Надеюсь, это кому-нибудь пригодится.

3 голосов
/ 28 февраля 2017

Если у вас есть свойство зависимости типа коллекции, помните следующее:

Если ваше свойство является ссылочным типом, значение по умолчанию, указанное в метаданных свойства зависимостей, не является значением по умолчанию для экземпляра; вместо этого это значение по умолчанию, которое применяется ко всем экземплярам типа. [...]
Чтобы исправить эту проблему, необходимо сбросить значение свойства зависимости коллекции в уникальный экземпляр, как часть вызова конструктора класса.

(см. MSDN Свойства зависимостей типа коллекции )

Чтобы ответить на вопрос Сэма (я только что столкнулся с той же проблемой):

Сделайте ваш обработчик CollectionChanged нестатичным и отмените подписку / повторную подписку на уровне экземпляра.

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 -= calendar.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 += calendar.SpecialDays_CollectionChanged;
  }
}

private void SpecialDays_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    // handle CollectionChanged on instance-level
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...