Подтвердить что ты не робот

Связывание с ExpandoObject. PropertyChanged не работает

В моем приложении Windows Store у меня есть список, заполненный ExpandoObjects. Связывание данных отлично работает для начальных значений, но не для свойства изображения, которое я устанавливал асинхронно после загрузки файла:

public static async void Set<T>(this ExpandoObject thisObject, string property, Func<Task<T>> setter) {
        var expando = thisObject as IDictionary<string, Object>;

        if (!expando.ContainsKey(property)) {
            expando.Add(property, null);
        }
        expando[property] = await setter.Invoke();
    }

Подключение к событию PropertyChanged в ExpandoObject подтверждает, что он запущен для всех объектов. Новое свойство привязано к объекту, и значение верное, но элементы в ListView не обновляются полностью.

Список содержит 14 объектов. Если я использую обычные типизированные объекты вместо ExpandoObjects и использую тот же параметр async свойства изображения, некоторые из 14 объектов обновляются в представлении (те, которые в настоящее время не видны). Если я реализую INotifyPropertyChanged в классе, все 14 обновляется. Используя ExpandoObjects, я получаю точное поведение, как и с типизированными объектами без INPC: обновляемые элементы не обновляются.

Поэтому кажется, что PropertyChanged не работает с ExpandoObject и привязкой данных.

Он работает как в WPF, но не в App Store. См. Сравнение: https://sites.google.com/site/moramatte/ExpandoComparison.zip?attredirects=0&d=1

4b9b3361

Ответ 1

Они не добавили механизм по умолчанию для привязки к динамическим объектам и вместо этого добавили новый интерфейс ICustomTypeProvider. И этот интерфейс также не был добавлен в ExpandoObject, но с помощью expando вы должны использовать привязку индексатора, поскольку это IDictionary<string, object>, который реализует INotifyPropertyChanged.

<TextBlock Text="{Binding [Foo]}"/>

Ответ 2

Переходя к этому снова, я пришел к выводу, что привязка не работает для обновлений атрибутов (обработанных с помощью INotifyPropertyChanged) для WinRT/Win10 (Build 10240) при использовании ExpandoObjects.

INotifyCollectionChanged работает - поэтому списки объектов ExpandoObject обновляются по мере их изменения, но их свойства неправильно подключены с помощью привязки.

Один способ обхода - создать объект значения и сохранить его в каждом свойстве expandoobject:

public class ValueHolder : INotifyPropertyChanged
{

  public ValueHolder(object v)
  {
    _value = v;
  }
  public event PropertyChangedEventHandler PropertyChanged;

  private object _value;
  public object Value
  {
    get { return _value; }
    set {
      if (_value != value)
      {
        _value = value;
        if (PropertyChanged != null)
        {
          PropertyChanged(this, new PropertyChangedEventArgs("Value"));
        }
      }
    }
  }
}

Затем я могу успешно связывать и получать обновления из свойств в expandoobjects следующим образом:

<TextBlock   Text='{Binding Path=Attribute1.Value }' MinWidth='20'/>

Я назначаю новые свойства следующим образом:

(theList[0] as dynamic).Attribute1 = new ValueHolder("a1");

Я обновляю такие свойства:

var listitem = (thelist[0] as dynamic);
  listitem.Attribute1.Value = "UPDATE";