2017-06-16 10 views
0

MVVMを使用してMVVMを使用してWPFアプリケーションにツリービューを構築しようとしていますが、HierarchicalDataTemplateを処理する方法がわかりません。私のTreeViewは、フォルダ内のフォルダなどを含むフォルダ構造を表す必要があります。次のようにMVAMを使用してTreeViewを構築するXAML定義

マイフォルダViewModelが定義されています:

public class TreeViewFolderViewModel : ViewModelBase 
{ 
    private int _id; 
    private int _parentId; 
    private string _text; 
    private string _key; 
    private ObservableCollection<TreeViewFolderViewModel> _children; 

    public int Id 
    { 
     get { return this._id; } 
     set { Set(() => Id, ref this._id, value); } 
    } 

    public int ParentId 
    { 
     get { return this._parentId; } 
     set { Set(() => ParentId, ref this._parentId, value); } 
    } 

    public string Text 
    { 
     get { return this._text; } 
     set { Set(() => Text, ref this._text, value); } 
    } 

    public string Key 
    { 
     get { return this._key; } 
     set { Set(() => Key, ref this._key, value); } 
    } 

    public ObservableCollection<TreeViewFolderViewModel> Children 
    { 
     get { return this._children ?? (this._children = 
       new ObservableCollection<TreeViewFolderViewModel>()); } 
     set { Set(() => Children, ref this._children, value); } 
    } 
} 

私のモデルは、最終的なViewModelは等々子フォルダが含まれているとフォルダのリストである私のViewModelと同じ構造を有しています。私はすべてのこれらのフォルダをロードするために再帰を使用しており、その部分は正常に動作しています。

私が立ち往生しているところは、このViewModelを定義して実際のTreeViewにロードする方法です。

私はHierarchical DataBinding in TreeView using MVVM patternを読んで、私は、多かれ少なかれ何が起こっているかを理解しながら、私のTreeViewは、1つのオブジェクトのみのタイプを持っていると私はどのようにと混乱している間、TreeViewのレベルのそれぞれが、異なるオブジェクトタイプを表しますこれを定義すると仮定します。

MainWindowViewModelのルートViewModelプロパティは、タイプTreeViewFolderViewModelです。つまり、ツリービューのルートを表す単一のオブジェクトを持っています。このオブジェクトは、順番に等々、私はXAMLでこれを定義しない方法

タイプTreeViewFolderViewModelの子供たちにも持っており、どのタイプTreeViewFolderViewModelの子供を持っていますか?

<TreeView Grid.Row="1" Margin="5,0,5,5" ItemsSource="{Binding RootFolder}"/> 
を私は次のように定義されたテンプレート Hierarchical持っている:

<Window.Resources> 
    <HierarchicalDataTemplate ItemsSource="{Binding Children}" 
    DataType="{x:Type viewmodels:SharePointFolderTreeViewViewModel}"> 
     <Label Content="{Binding Name}"/> 
    </HierarchicalDataTemplate> 
</Window.Resources> 

しかし、何がアップロードされていないが、私は次のように定義されています。

私はこれをどのように解決することができますか?

ありがとうございました。

答えて

1

説明するために小さなサンプルを用意しました。

のviewmodels

public class TreeViewFolderViewModel : ViewModelBase 
{ 
    private int id; 
    public int Id 
    { 
     get { return id; } 
     set { id = value; OnPropertyChanged("Id"); } 
    } 

    private string text; 
    public string Text 
    { 
     get { return text; } 
     set { text = value; OnPropertyChanged("Text"); } 
    } 

    private ObservableCollection<TreeViewFolderViewModel> children; 
    public ObservableCollection<TreeViewFolderViewModel> Children 
    { 
     get 
     { 
      return children ?? (children = 
      new ObservableCollection<TreeViewFolderViewModel>()); 
     } 
     set { children = value; OnPropertyChanged("Children"); } 
    } 
} 

public class TreeViewModel : ViewModelBase 
{ 
    private List<TreeViewFolderViewModel> items; 
    public List<TreeViewFolderViewModel> Items 
    { 
     get { return items; } 
     set { items = value; OnPropertyChanged("Items"); } 
    } 

    public TreeViewModel() 
    { 
     Items = new List<TreeViewFolderViewModel>() 
     { 
      new TreeViewFolderViewModel() 
      { 
       Id =0, Text="RootFolder", Children=new ObservableCollection<TreeViewFolderViewModel>() 
       { 
        new TreeViewFolderViewModel() { Id = 10, Text = "FirstFolder", Children=new ObservableCollection<TreeViewFolderViewModel>() { new TreeViewFolderViewModel() { Id = 11, Text = "FirstChild" } } } , 
        new TreeViewFolderViewModel() { Id = 20, Text = "SecondFolder", Children = new ObservableCollection<TreeViewFolderViewModel>() { new TreeViewFolderViewModel() { Id = 21, Text = "SecondChild" } } } , 
        new TreeViewFolderViewModel() { Id = 30, Text = "ThirdFolder", Children = new ObservableCollection<TreeViewFolderViewModel>() { new TreeViewFolderViewModel() { Id = 31, Text = "ThirdChild" } } } 
       } 
      } 
     }; 
    } 
} 

public class ViewModelBase : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    protected void OnPropertyChanged(string propName) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName)); 
    } 
} 

MainWindow.xaml

<Window x:Class="WpfApp.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:WpfApp" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.DataContext> 
     <local:TreeViewModel /> 
    </Window.DataContext> 

    <Window.Resources>  
     <HierarchicalDataTemplate ItemsSource="{Binding Children}" 
            DataType="{x:Type local:TreeViewFolderViewModel}"> 
      <TextBlock> 
       <TextBlock.Text> 
        <MultiBinding StringFormat="{}{0} {1}"> 
         <Binding Path="Id" /> 
         <Binding Path="Text" /> 
        </MultiBinding> 
       </TextBlock.Text> 
      </TextBlock> 
     </HierarchicalDataTemplate>  
    </Window.Resources> 

    <Grid> 
     <TreeView ItemsSource="{Binding Items}" /> 
    </Grid> 
</Window> 
+0

それはまだ私のために働いていないように私は何かが欠けている必要があります。私のTreeViewのItemSourceは間違いなく正しく設定されています。私は 'HierarchicalDataTemplate'をあなたのものに合わせて変更しました(実際は同じです)。私の最大の間違いは、実際にリスト自体の一部であったはずのノードとしてルートを扱うことでした。私はその部分を修正しました。最終的なリストは、子リストプロパティのルートノードを含むリストであり、これらの子それぞれは独自の子を持っています。唯一の違いは、リストの代わりにObservableCollectionを使用していることです。何か案は?ありがとう。 – Thierry

+0

出力ウィンドウに次のエラーが表示されています。 System.Windows.Dataエラー:40:BindingExpressionパスエラー: 'Children'プロパティが 'object'に見つかりません 'ObservableCollection'1'(HashCode = 51831188) ' BindingExpression:Path = Folders。子供; DataItem = 'ChooseFolderDialogViewModel'(HashCode = 9691954);ターゲット要素は 'TreeView'(Name = '')です。ターゲットプロパティは 'ItemsSource'(タイプ 'IEnumerable')です。それは明らかに私のツリービューがまだ空である理由です。私は何かを見つけたらそれを調べて更新し続けます。 – Thierry

+1

私の問題が見つかりました。 'ItemsSource =" {Binding Folders} "と思っていたとき、私は愚かに' ItemsSource = "{Binding Folders.Children}"を残しました。期待通りにすべてが読み込まれています。要するに、フォルダのリストの子としてルートを追加する必要があります。もう一度多くの感謝! – Thierry

関連する問題