Reputation: 1808
This question is a follow up to this question. I've taken some advice from this site and decided to start learning MVVM implementation for my work with TreeViews. With that being said I am VERY new to MVVM and I'm still getting familiar with the syntax and implementation.
I have a TreeView that displays integer-type data but I would like it to work with strings instead. The tree also allows the user to add to any level by selecting the TreeViewItem and then typing in the new integer header into the textBox, and then clicking a button.
I'd like for a parent, child, and grandchild to be available at start-up with pre-defined names. Another thing to note is that that user will only be able to add to the TreeView at the level of the child (so they'll only be able to add grandchildren).
Model
public class TreeViewModel : PropertyChangedBase
{
public string Value { get; set; }
public ObservableCollection<TreeViewModel> Items { get; set; }
public CollectionView ItemsView { get; set; }
public TreeViewModel(string value)
{
Items = new ObservableCollection<TreeViewModel>();
ItemsView = new ListCollectionView(Items)
{
SortDescriptions =
{
new SortDescription("Value",ListSortDirection.Ascending)
}
};
Value = value;
}
}
ViewModel
public class SortedTreeViewWindowViewModel : PropertyChangedBase
{
private string _newValueString;
public string NewValueString
{
get { return _newValueString; }
set
{
_newValueString = value;
OnPropertyChanged("NewValueString");
}
}
public TreeViewModel SelectedItem { get; set; }
public ObservableCollection<TreeViewModel> Items { get; set; }
public ICollectionView ItemsView { get; set; }
public SortedTreeViewWindowViewModel()
{
Items = new ObservableCollection<TreeViewModel>();
ItemsView = new ListCollectionView(Items) { SortDescriptions = { new SortDescription("Value", ListSortDirection.Ascending) } };
}
public void AddNewItem()
{
ObservableCollection<TreeViewModel> targetcollection;
//Insert the New Node as a Root node if nothing is selected.
targetcollection = SelectedItem == null ? Items : SelectedItem.Items;
if (_newValueString != null)
{
targetcollection.Add(new TreeViewModel(_newValueString));
NewValueString = string.Empty;
}
}
}
View Code-Behind
public partial class Window1 : Window
{
public SortedTreeViewWindowViewModel ViewModel { get { return DataContext as SortedTreeViewWindowViewModel; } set { DataContext = value; } }
public Window1()
{
InitializeComponent();
ViewModel = new SortedTreeViewWindowViewModel()
{
Items = {new TreeViewModel("Test")}
};
}
private void AddNewItem(object sender, RoutedEventArgs e)
{
ViewModel.AddNewItem();
}
private void OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
ViewModel.SelectedItem = e.NewValue as TreeViewModel;
}
}
Thanks so much for the help. I'm hoping that going through this will help me understand how to edit and build ViewModels so that I can learn to improvise a little more in the future.
UPDATE
The TreeView is now composed of strings, so that part is solved. I still need help with the default nodes though. I have updated my code to reflect this change.
Upvotes: 1
Views: 4062
Reputation: 961
Here are my suggestions
Here is a very simple example how to fill a tree in the ViewModel which is bound to a TreeView in the View:
View
<Window x:Class="TreeViewExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<StackPanel>
<TreeView ItemsSource="{Binding Tree}"/>
</StackPanel>
</StackPanel>
</Window>
View Code-Behind
namespace TreeViewExample
{
using System.Windows;
public partial class MainWindow : Window
{
public MainWindow()
{
DataContext = new MainWindowViewModel();
InitializeComponent();
}
}
}
ViewModel
namespace TreeViewExample
{
using System.Collections.ObjectModel;
using System.Windows.Controls;
class MainWindowViewModel
{
public ObservableCollection<TreeViewItem> Tree { get; set; }
public MainWindowViewModel()
{
Tree = new ObservableCollection<TreeViewItem>();
Tree.Add(GetLoadedTreeRoot());
}
private TreeViewItem GetLoadedTreeRoot()
{
TreeViewItem parent = new TreeViewItem() { Header = "Parent" };
TreeViewItem child1 = new TreeViewItem() { Header = "Child 1" };
TreeViewItem child2 = new TreeViewItem() { Header = "Child 2" };
TreeViewItem grandchild1 = new TreeViewItem() { Header = "Grandchild 1" };
TreeViewItem grandchild2 = new TreeViewItem() { Header = "Grandchild 2" };
child1.Items.Add(grandchild1);
child2.Items.Add(grandchild2);
parent.Items.Add(child1);
parent.Items.Add(child2);
return parent;
}
}
}
Produces:
Additional thoughts:
Upvotes: 3