绑定到ExpandoObject。 PropertyChanged无法正常工作

时间:2012-11-29 07:17:32

标签: .net dynamic binding expandoobject

在我的Windows应用商店应用中,我有一个填充了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();
    }

连接到ExpandoObject上的PropertyChanged事件,确认它是针对所有对象触发的。 新属性附加到对象,值正确,但ListView中的项目不会完整更新。

该列表包含14个对象。如果我使用常规类型对象而不是ExpandoObjects并使用相同的图像属性异步设置,则14个对象中的一些将在视图中更新(当前不可见的对象)。如果我在类中实现了INotifyPropertyChanged,那么所有14个都会更新。 使用ExpandoObjects我得到的确切行为与没有INPC的类型对象一样:更新当前不可见的项目。

所以看起来PropertyChanged没有使用ExpandoObject和数据绑定。

它可以在WPF中按预期工作,但不能在Store App中使用。看比较: https://sites.google.com/site/moramatte/ExpandoComparison.zip?attredirects=0&d=1

2 个答案:

答案 0 :(得分:1)

他们没有添加绑定到动态对象的默认机制,而是添加了一个新接口ICustomTypeProvider。并且该接口也没有添加到ExpandoObject,但是使用expando,您应该能够使用索引器绑定,因为它是IDictionary<string, object>,它实现了INotifyPropertyChanged

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

答案 1 :(得分:0)

再次讨论这个问题我得出结论,当使用ExpandoObjects时,绑定不适用于WinRT / Win10(Build 10240)的属性更新(使用INotifyPropertyChanged处理的属性)。

INotifyCollectionChanged有效 - 因此ExpandoObjects列表会随着它们的更改而更新 - 但它们的属性未被Binding正确连接。

一种解决方法是创建一个值对象并将其保留在每个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";