2016-09-22 4 views
0

У меня есть приложение UWP, в котором используется управляемый SDK поведения UWP. Я написал пользовательское поведение, которое имеет два свойства зависимостей, одним из которых является ObservableCollection.Xaml Behavior DP не обновляется

Всякий раз, когда я обновляю элемент в коллекции, я убеждаюсь, что PropertyChanged вызывается для коллекции.

Однако свойство Dependency не обновляется.

Мой код:

<trigger:CustomBehavior ItemIndex="{x:Bind ItemIndex}" 
    Presences="{Binding ElementName=Box, 
     Path=DataContext.CustomCollection, 
      UpdateSourceTrigger=PropertyChanged, Converter={StaticResource TestConverter}}" /> 

Мой TestConverter показывает мне, что когда я обновить элемент в сборе, триггер updatesource работает. Однако свойство зависимостей в моем поведении не запускает событие Changed. Когда я изменяю всю пользовательскую коллекцию, DP обновляется, когда я просто меняю один элемент, это не так.

Исследования показывают, что DependencyObject.SetValue просто проверяет, изменился ли объект, и если один элемент изменился, он просто подумает, что коллекция не изменилась вообще? Это правда, и если да, то как я могу это преодолеть?

Благодаря

+0

Примечание: «Когда я обновляю элемент в коллекции, триггер обновления источника работает», это распространенное недоразумение. Установка «UpdateSourceTrigger = PropertyChanged» в односторонней привязке не влияет, она только контролирует, как источник привязки обновляется при изменении цели, то есть эффективен только для двусторонних или однонаправленных привязок. Тем не менее, обновление элемента в коллекции, а затем создание события PropertyChanged также не имеет никакого эффекта, поскольку экземпляр * коллекции * не изменился, и событие PropertyChanged игнорируется. – Clemens

+0

Либо вы заменяете всю коллекцию, либо регистрируете обработчик события 'INotifyCollectionChanged.CollectionChanged' в свойстве PropertyChangedCallback of Presences. – Clemens

+0

Красивые. Можете ли вы опубликовать это как ответ, чтобы я мог принять его? – WJM

ответ

2

Свойства зависимостей коллекции типа обычно должно быть объявлено как наиболее основным типа сбора, IEnumerable. Таким образом, вы можете назначить множество фактических типов сбора для свойства, включая те, которые реализуют INotifyCollectionChanged, например ObservableCollection<T>.

Вы проверили бы во время выполнения, если тип коллекции фактически реализует интерфейс и, возможно, присоединяет и отделяет метод обработчика для события CollectionChanged.

public class CustomBehavior : ... 
{ 
    public static readonly DependencyProperty PresencesProperty = 
     DependencyProperty.Register(
      "Presences", typeof(IEnumerable), typeof(CustomBehavior), 
      new PropertyMetadata(null, 
       (o, e) => ((CustomBehavior)o).OnPresencesPropertyChanged(e))); 

    private void OnPresencesPropertyChanged(DependencyPropertyChangedEventArgs e) 
    { 
     var oldCollectionChanged = e.OldValue as INotifyCollectionChanged; 
     var newCollectionChanged = e.NewValue as INotifyCollectionChanged; 

     if (oldCollectionChanged != null) 
     { 
      oldCollectionChanged.CollectionChanged -= OnPresencesCollectionChanged; 
     } 

     if (newCollectionChanged != null) 
     { 
      newCollectionChanged.CollectionChanged += OnPresencesCollectionChanged; 
      // in addition to adding a CollectionChanged handler, any 
      // already existing collection elements should be processed here 
     } 
    } 

    private void OnPresencesCollectionChanged(
     object sender, NotifyCollectionChangedEventArgs e) 
    { 
     // handle collection changes here 
    } 
}