1

我有一个基于分组模板项目的 Windows 8 商店应用程序,并进行了一些重命名等。但是,我很难让 ItemsSource 数据绑定同时适用于捕捉和捕捉的视觉状态。

我有一个属性,它在设置时会更改 ItemsSource 属性,但我一次只能获取一个要绑定的控件(对于未捕捉的 GridView 或用于捕捉的 ListView)。

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

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

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

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

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

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

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

Since I am generating my data model on another thread (yes, using the thread pool), I cannot make it inherit from DependencyObject. If I do, I get a WrongThreadException.

So to make it work I have done the following:

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>();
}

and then my items look like this:

  // 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;
  }
}

Is there something I'm doing fundamentally wrong?

Help appreciated.

Thanks!

4

2 回答 2

1

Thankfully there is a much easier way to do what you are trying!

Create a class called your ViewModel as shown below:

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

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

}

Now on the code behind set the Page.DataConected to equal an instance of the above class.

And finally on both your snapped listview, and the grid view set the item source to this:-

ItemsSource="{Binding Data}"

That should work nicely for you.

于 2012-12-22T09:57:45.517 回答
0

Thanks to Ross for pointing me in the right direction.

I'm not 100% happy with this solution, but it does work. Basically the idea is that after I get back the PickLeafModel from the worker threads, I transplant its internal data into a derived version of the class which is data binding aware.

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();
  }

and the page code is as follows:

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

  set
  {
    DataContext = value;
  }
}

whenever I want to set ListViewModel, I can do this:

  ListViewModel = new PickLeafViewModel(model); 

and swap looks like:

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);
  ...

Also, PickLeafModelViewDataEnumerator can be deleted altogether.

于 2012-12-28T08:57:18.030 回答