3


1

WPF TreeView HierarchicalDataTemplate-異なる子コレクションを持つオブジェクトへのバインド

データテンプレートを使用してコレクションをwpf `TreeView`コントロールにバインドしようとしています。 コレクション内の各アイテム(Person)には、タイプcarとbookの2つの異なるコレクション(Cars、Books)も含まれています。

以下は、スペースを節約するために関係するオブジェクトの簡略化されたリストです。

public class Person
{
  public string Name
  public List Books;
  public List Cars;
}

public class Book
{
  public string Title
  public string Author
}

public class Car
{
  public string Manufacturer;
  public string Model;
}

ここに私が拘束している方法があります

    public MainWindow()
    {
        InitializeComponent();

        this.treeView1.ItemsSource = this.PersonList();
    }

    public List PersonList()
    {
        List list = new List();


        Book eco = new Book { Title = "Economics 101", Author = "Adam Smith"};
        Book design = new Book { Title = "Web Design", Author = "Robins" };

        Car corola = new Car { Manufacturer = "Toyota", Model = "2005 Corola"};
        Car ford = new Car { Manufacturer = "Ford", Model = "2008 Focus"};

        Person john = new Person { Name = "John", Books = new ObservableCollection { eco, design }, Cars = new ObservableCollection { corola } };

        Person smith = new Person { Name = "Smith", Books = new ObservableCollection { eco, design }, Cars = new ObservableCollection { ford } };

        list.AddRange(new[] {john, smith });
        return list;
    }

これがXamlコードです


このように見えるツリー表示を探しています。

>John
  >Books
    Economics 101 : Adam Smith
    Web Design    : Robins
  >Cars
    Totota : 2005 Corola
>Smith
  >Books
    Economics 101 : Adam Smith
    Web Design    : Robins
  >Cars
    Ford: 2008 Focus

この記号「>」はツリーフォルダを示すために使用され、テンプレートでは考慮されません。

3 Answer


7


ツリーには2つの異なる子コレクションがあるため、少し複雑です。 WPFは、複数の `ItemsSource`定義があるシナリオをサポートしていません。 したがって、これらのコレクションをhttp://msdn.microsoft.com/en-us/library/system.windows.data.compositecollection.aspx[CompositeCollection]に結合する必要があります。 複合要素のタイプマッチング(つまり、 車、本)は自動的に行われます。

XAMLでは、タイプ定義に一致するいわゆるhttp://msdn.microsoft.com/en-us/library/system.windows.hierarchicaldatatemplate.aspx[HierarchicalDataTemplates]を定義する必要があります。 「local」が「Book」、「Car」、「Person」が定義されている名前空間を指している場合、簡略化された「HierarchicalDataTemplates」は次のようになります。


次に、コレクションをツリーコントロールに接続する必要があります。 これを行う方法はいくつかありますが、最も簡単なのは、 `Window`クラスでプロパティを定義し、Bindingを定義することです。


これは正しい方向を指し示しますが、私のコードをコンパイル準備完了とみなさないでください:-)


3


「CompositeCollection」は良い答えです。ただし、子コレクションを「DataContext」にバインドできないのは、「Freezable」ではないためです。 それらはリソースにのみバインドできます。 (詳細については、https://stackoverflow.com/questions/1189052/why-is-compositecollection-not-freezable [この質問]を参照してください。)それは、 ItemsSource`を使用するには、現在のコンテキストのプロパティにバインドする必要があります。

コレクションの変更通知が必要ない場合は、ビューモデルにプロパティを簡単に実装できます。例:

public IEnumerable Items
{
   get { return Books.Concat(Cars); }
}

コレクションの変更通知が必要な場合は、それほど簡単ではありません。


1


`DataTemplate`が必要です。そうでなければ、WPFはオブジェクトの表示方法を知りません。