DataContext和GridView / ListView的奇怪之处

时间:2012-12-22 01:40:25

标签: data-binding windows-8 windows-runtime windows-store-apps

我有一个基于分组模板项目的Windows 8商店应用程序,有一些重命名等。但是,我很难让ItemsSource数据绑定工作两个非snapped并拍摄视觉状态。

我有一个属性,设置后会更改ItemsSource属性,但我一次只能获得一个要绑定的控件(GridView用于非snapped,或者ListView用于snapped)。

当我使用以下内容时,只有非捕捉的绑定有效,而捕捉的绑定不显示任何项目:

protected PickLeafModel ListViewModel
{
  get
  {
    return (PickLeafModel)m_itemGridView.ItemsSource;
  }

  set
  {
    m_itemGridView.ItemsSource = value;
    m_snappedListView.ItemsSource = value;
  }
}

如果我注释掉其中一个setter,则捕捉的视图会显示项目,但非捕捉的视图不会显示任何内容:

protected PickLeafModel ListViewModel
{
  get
  {
    return (PickLeafModel)m_itemGridView.ItemsSource;
  }

  set
  {
    //m_itemGridView.ItemsSource = value;
    m_snappedListView.ItemsSource = value;
  }
}

就好像我一次只能将我的视图模型绑定到一个属性。我做错了什么?

由于我在另一个线程上生成我的数据模型(是的,使用线程池),我不能让它继承自DependencyObject。如果我这样做,我会得到一个WrongThreadException。

为了使其成功,我做了以下工作:

public class PickLeafModel : IEnumerable
{
  public PickLeafModel()
  {
  }

  public IEnumerator GetEnumerator()
  {
    if (m_enumerator == null)
    {
      m_enumerator = new PickLeafModelViewDataEnumerator(m_data, m_parentLeaf);
    }

    return m_enumerator;
  }

  private SerializableLinkedList<PickLeaf> m_data = 
    new SerializableLinkedList<PickLeaf>();
}

然后我的项目看起来像这样:

  // Augments pick leafs by returning them wrapped with PickLeafViewData.
  class PickLeafModelViewDataEnumerator : IEnumerator
  {
    public PickLeafModelViewDataEnumerator(
      SerializableLinkedList<PickLeaf> data, PickLeaf parentLeaf)
    {
      m_viewDataList =
        new System.Collections.Generic.LinkedList<PickLeafViewData>();

      foreach (PickLeaf leaf in data)
      {
        PickLeafViewData viewData = new PickLeafViewData();
        viewData.copyFromPickLeaf(leaf, parentLeaf);
        m_viewDataList.AddLast(viewData);
      }

      m_enumerator = m_viewDataList.GetEnumerator();
    }

    public void Dispose()
    {
      m_viewDataList = null;
      m_enumerator = null;
    }

    public object Current
    {
      get
      {
        return m_enumerator.Current;
      }
    }

    public bool MoveNext()
    {
      return m_enumerator.MoveNext();
    }

    public void Reset()
    {
      m_enumerator.Reset();
    }

    private IEnumerator<PickLeafViewData> m_enumerator = null;

    private System.Collections.Generic.LinkedList<PickLeafViewData>
      m_viewDataList;
  }
}

我在做什么根本就错了吗?

帮助表示赞赏。

谢谢!

2 个答案:

答案 0 :(得分:1)

值得庆幸的是,有一种更简单的方法来做你正在尝试的事情!

创建一个名为ViewModel的类,如下所示:

public class DataViewModel
{
    public DataViewModel()
    {
        Data = new ObservableCollection<PickLeafViewData>(new PickLeafModelViewDataEnumerator(m_data, m_parentLeaf));             
    }

    public ObservableCollection<PickLeafViewData> Data
    {
        get;
        set;
    }

}

现在在后面的代码中,将Page.DataConected设置为等于上述类的实例。

最后在你的快照列表视图上,网格视图将项目源设置为: -

ItemsSource="{Binding Data}"

这应该很适合你。

答案 1 :(得分:0)

感谢罗斯指出我正确的方向。

我对此解决方案并不十分满意,但确实有效。基本上我的想法是,在从工作线程返回PickLeafModel之后,我将其内部数据移植到可以识别数据绑定的类的派生版本中。​​

public class PickLeafViewModel : PickLeafModel, IEnumerable
{
  public PickLeafViewModel()
  {
  }

  public PickLeafViewModel(PickLeafModel model)
  {
    SetData(model);
  }

  public void SetData(PickLeafModel model)
  {
    model.swap(this);
  }

  public IEnumerator GetEnumerator()
  {
    if (m_observableData == null)
    {
      m_observableData = new ObservableCollection<PickLeafViewData>();

      var data = getData();
      PickLeaf parentLeaf = getParentLeaf();
      foreach (PickLeaf leaf in data)
      {
        PickLeafViewData viewData = new PickLeafViewData();
        viewData.copyFromPickLeaf(leaf, parentLeaf);
        m_observableData.Add(viewData);
      }
    }

    return m_observableData.GetEnumerator();
  }

,页面代码如下:

protected PickLeafViewModel ListViewModel
{
  get
  {
    return DataContext as PickLeafViewModel;
  }

  set
  {
    DataContext = value;
  }
}

每当我想设置ListViewModel时,我都可以这样做:

  ListViewModel = new PickLeafViewModel(model); 

和交换看起来像:

private static void swap<T>(ref T lhs, ref T rhs)
{
  T temp;
  temp = lhs;
  lhs = rhs;
  rhs = temp;
}

// Swaps internals with the other model.
public void swap(PickLeafModel other)
{
  swap(ref m_data, ref other.m_data);
  ...

此外,可以完全删除PickLeafModelViewDataEnumerator。