MVVM treeview wpf(binding?)

18,018

Solution 1

The following code is a quick hack of your application. I also understood that you have problems with the treeview so i only display the code passanges to the treeview and i fill my books list inside the constructor of my view model to have some data

Model:

internal class Book : NotifyPropertyChangedBase
{
    private string name;
    private BookType type;
    public BookType Type
    {
       get => this.type;
    }
    set
    {
        this.SetProperty( ref this.type,value );
    }
}

public string Name
{
    get => return this.name;
    set
    {
        this.SetProperty( ref this.name,value );
    }
}

ViewModel:

private readonly List<Book> books;

public MainViewModel( )
{
    this.books = new List<Book>
    {
        new Book
        {
            Name = "Book 1",
            Type = BookType.Fantasy
        },
        new Book
        {
            Name = "Book 2",
            Type = BookType.Fantasy
        },
        new Book
        {
            Name = "Book 3",
            Type = BookType.Fantasy
        },
        new Book
        {
            Name = "Book 4",
            Type = BookType.SciFi
        }
    };
}

public ICollectionView Books
{
    get
    {
        var source = CollectionViewSource.GetDefaultView( this.books );
        source.GroupDescriptions.Add( new PropertyGroupDescription( "Type" ) 
    );
    return source;
}

View:

<TreeView ItemsSource="{Binding Books.Groups}">
  <TreeView.ItemTemplate>
    <HierarchicalDataTemplate ItemsSource="{Binding Items}">
      <TextBlock Text="{Binding Name}" />
    </HierarchicalDataTemplate>
  </TreeView.ItemTemplate>
</TreeView>

Solution 2

From what I understand you need help generating the hierarchy in TreeView using a ViewModel. Todo this you will be using a HierarchicalDataTemplate. Your ViewModel will require a collection of children, and you will use the simply bind the ItemsSource property of the HierarchicalDataTemplate to that collection.

Take a look at this simple example someone made: TreeView and HierarchicalDataTemplate, Step-by-Step

Share:
18,018

Related videos on Youtube

curiousity
Author by

curiousity

gentleman and a scholar

Updated on September 16, 2022

Comments

  • curiousity
    curiousity over 1 year

    Sorry for noob question. Perhaps this is not a question - but I need a tutorial sample/ I am trying to write a model task to get "handy" with mvvm pattern in wpf. I am decide to write something like librarian helper. That is one simple wpf window with one combobox(for selecting if the book is fantasy or sf), textbox (for book name input), button Add, and a treeview with a tree like:

     Books
      ------>ScienceFic
            ----->bookName1
            ----->bookName2
      ------->Fantasy
            ------>bookName3
    

    And I have some difficulties with binding and separation view model from view. Could You help me?

    public enum LibraryType
    {
        ScienceFic,
        Fantasy
    }
        Class Model: INotifyPropertyChanged
        {
         private int bookId;
         private string bookName;
         private LibraryType bookType;
         public event PropertyChangedEventHandler PropertyChanged;
            //....and for all this fields  I have used a INotifyPropertyChanged as 
        /*
        http://stackoverflow.com/questions/1315621/implementing-inotifypropertychanged-does-a-better-way-exist
        */
        }
    

    At this point the MODEL is finished I think.

    Now about VIEW: I have simply open editor of MainWindow and manually added button, textbox, combobox, and a treeview. After addition of

    comboBox1.ItemsSource = Enum.GetValues(typeof(LibraryType)).Cast<LibraryType>();
     comboBox1.SelectedIndex = 0;
    

    I have initialized my combo with right types of books))) But((, I have done this in code, not in XAML - is this right for MVVM Binding? (first question) Next, I have bind (as I suppose) my textBox text to current book name property in ViewModel (I have done this in XAML like this):

     <TextBox Text="{Binding Path=CurrentBookName}"/>
    

    is this right? (second question)

    And, finally, VIEWMODEL

     Class ViewModel
    {
      private string currentBookName;
      private LibraryType selectedBookType;
      public event PropertyChangedEventHandler PropertyChanged;
      //also properties and  OnPropertyChanged/SetField functions like in Model class
    
      //and finally I have created two lists for book storing
      private List<Model> sfStorage = new List<Model>();
      private List<Model> fantasyStorage = new List<Model>();
      //and simple getters for this two lists, like:
      public List<Model> GetSFStorage
      {
       get{return this.sfStorage;}
      }
      //and a simple function for addition of new books
      //that I plan to call when AddButton pressed
      public void Addition(???)
            {
                if (!string.IsNullOrEmpty(currentBookName))
                {
                    //? I have add CurrentBookName in XAML of View (see above)
                    //?but is it enough to have a property of CurrentBookType
                    //to grant that a valide value from combobox will be here?
                    var modelNewBook = new Model(CurrentBookName,CurrentBookType);
                    switch (selectedBookType)
                    {
                        case LibraryType.ScienceFic:
                            sfStorage.Add(modelNewBook);
                            break;
                        case LibraryType.Fantasy:
                            fantasyStorage.Add(modelNewBook);
                            break;
                        default:
                            return;
                    }
                }
    }
    

    Now I am only few step out of success (may be) BUT, how I could connect a treeView with this two lists in xaml or in code And how could I call Addition function when an Addbutton pressed (third and main question)? Perhaps, this is noob question, but I really need an sample. And, (perhaps) this question will be helpfull for others who try to understand MVVM and binding.

  • curiousity
    curiousity over 10 years
    I have tried to do binding as you say but treeview itself is still void(( it seems that debuger even not get to MainViewModel( ). Also - this approach will not give void tree on first step - Books and two su folders SF and fantasy without any books in them. But usage of collection is marvelous) I am tring to implement it
  • Sukram
    Sukram over 10 years
    In my quick hack i set the data context in the constructor of the view. Like: public MainWindow( ) { this.InitializeComponent( ); this.ViewModel = new MainViewModel( ); } public MainViewModel ViewModel { set { this.DataContext = value; } get { return this.DataContext as MainViewModel; } }