WPF: Что может привести к тому, что источник привязки не будет обновлен? - PullRequest
1 голос
/ 30 октября 2009

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

У меня есть изображение TIFF из базы данных, которое отображается как свойство типа System.Data.Linq.Binary. Я хочу отобразить отдельные кадры из этого изображения TIFF в формате ItemsControl, поэтому я написал конвертер, который принимает тип данных Binary и возвращает ObservableCollection BitmapFrames. Я связываю ItemsControl.ItemsSource с двоичным свойством, используя конвертер вместе с "Mode=TwoWay" и "UpdateSourceTrigger=PropertyChanged".

Отображение изображений работает нормально. Проблема заключается в том, что, если я добавлю рамку в коллекцию, дисплей обновится, но это изменение не будет передано обратно в свойство Binary исходного объекта. Метод ConvertBack() в моем конвертере никогда не вызывается (что указывает на то, что привязка никогда даже не пытается обновить источник). Если я вручную вызову BindingExpression.UpdateSource(), как если бы он был установлен для "UpdateSourceTrigger=Explicit", свойство Binary обновляется правильно.

Итак, если для "Mode=TwoWay" и "UpdateSourceTrigger=PropertyChanged" установлена ​​привязка и объект реализует INotifyPropertyChanged (что делает ObserverableCollection), почему привязка на самом деле не пытается обновить источник?

Спасибо!

Ответы [ 2 ]

2 голосов
/ 30 октября 2009

Это происходит потому, что для привязок TwoWay WPF обнаруживает только когда свойство получает новое значение, а не когда объект, на который ссылается свойство, изменяется.

В вашем случае ваша собственность содержит коллекцию ObservableCollection, созданную вашим конвертером. Хотя содержимое ObservableCollection было изменено и оно запускает INotifyPropertyChanged, само свойство привязки не изменилось: оно по-прежнему ссылается на тот же ObservableCollection, что и раньше. Из-за этого WPF DataBinding не запускается и ваш источник не обновляется.

Когда вы вызываете UpdateSource () вручную, он заставляет ObservableCollection проходить через ваш конвертер и обратно к вашему объекту данных, поэтому он работает.

Самый простой способ получить желаемое поведение:

  1. Вместо привязки к полю данных, привязка к объекту данных и извлечение нужного поля в конвертере (если вы хотите создать универсальный конвертер, который может получить доступ к любому полю, передайте поле в качестве параметра) .

  2. В преобразователе при создании ObservableCollection добавьте событие CollectionChanged, которое обновляет исходный объект при каждом его запуске.

Вот общая идея в коде:

  public MyConverter : IValueConverter
  {
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
      PropertyInfo property = object.GetType().GetProperty((string)parameter);

      var coll = BinaryToCollection((Binary)property.GetValue(object, null));

      coll.CollectionChanged += (sender, e) =>
      {
        property.SetValue(object, CollectionToBinary(coll));
      };
      return coll;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
      throw new NotImplementedException();
    }

    private ObservableCollection<SomeType> BinaryToCollection(Binary data)
    {
      // conversion details here
    }

    private Binary CollectionToBinary(ObservableCollection<SomeType> coll)
    {
      // conversion details here
    }

  }

В этом случае ваша привязка изменится с

 <ItemsControl ItemsSource="{Binding something.property, Mode=TwoWay, Converter={...}}"

до

  <ItemsControl ItemsSource="{Binding something, Converter={...}}"

с параметром преобразователя, являющимся именем свойства

Надеюсь, это поможет!

2 голосов
/ 30 октября 2009

Я успешно использовал эту запись в блоге для устранения проблем с привязкой. В частности, метод "TraceLevel".

Bea Stollnitz - Как отладить привязки WPF?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...