1

グループ化されたテンプレート プロジェクトに基づいた Windows 8 ストア アプリがあり、いくつかの名前が変更されています

設定すると ItemsSource プロパティが変更されるプロパティがありますが、一度にバインドできるコントロールは 1 つだけです (スナップされていない場合は GridView、スナップされている場合は ListView)。

以下を使用すると、スナップされていないバインディングのみが機能し、スナップされたバインディングにはアイテムが表示されません。

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

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

セッターの 1 つをコメントアウトすると、スナップされたビューにはアイテムが表示されますが、スナップされていないビューには何も表示されません。

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

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

ビュー モデルを一度に 1 つのプロパティにのみバインドできるかのようです。私は何を間違っていますか?

別のスレッドで (はい、スレッド プールを使用して) データ モデルを生成しているため、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;
  }
}

私が根本的に間違っていることはありますか?

助けていただければ幸いです。

ありがとう!

4

2 に答える 2

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}"

それはあなたにとってうまくいくはずです。

于 2012-12-22T09:57:45.517 に答える
0

私を正しい方向に向けてくれたロスに感謝します。

このソリューションに 100% 満足しているわけではありませんが、うまくいきます。基本的には、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 をまとめて削除することもできます。

于 2012-12-28T08:57:18.030 に答える