I'm working on a small "fun" project using WPF/MVVM/Prism which main component is a TreeView showing the file structure of a certain path. The idea how the ViewModel works is taken from Josh Smiths' article http://www.codeproject.com/Articles/28306/Working-with-Checkboxes-in-the-WPF-TreeView.
I actually need two things:
- I'd like to get a list of checked items of the TreeView-View, presented in a another view (let's say List-View) and also show that the their state has changed.
- I'd like to modify the List-View, which shall then be reflected within the TreeView.
Somehow I did not find a nice solution, as the hierarchical ViewModel used by Josh makes it hard for me to get hold on a "shared" model useable within both ViewModels.
But let's have a look at my code before stating my question:
My "ExplorerView" uses a hierarchical datatemplate and looks as follows:
<UserControl x:Class="MyFunProject.Views.ExplorerView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ViewModel="clr-namespace:MyFunProject.ViewModels"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True">
<UserControl.Resources>
<HierarchicalDataTemplate DataType="{x:Type ViewModel:ItemBaseViewModel}" ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<CheckBox Focusable="True" IsChecked="{Binding IsChecked}" VerticalAlignment="Center" ToolTip="{Binding Path}">
<TextBlock Text="{Binding Name}" />
</CheckBox>
</StackPanel>
</HierarchicalDataTemplate>
</UserControl.Resources>
<TreeView ItemsSource="{Binding Children}" />
</UserControl>
Following Josh's article, the ExplorerViewModel exhibits a child as a List<CheckableItemViewModel>
with only one entry - which in fact has other childs directories or files. Directories itself again have childs.
public class ExplorerViewModel : BindableBase
{
private List<CheckableItemViewModel> childred;
public List<CheckableItemViewModel> Children
{
get { return childred; }
set { SetProperty(ref childred, value); }
}
public ExplorerViewModel(IExplorerModel ExplorerModel)
{
CheckableItemViewModel root = new CheckableItemViewModel();
AddChildrenToNode(root, ExplorerModel.GetCheckableItems());
root.Initialize(); // initialize children (and each children its own children, etc...)
Children = new List<CheckableItemViewModel> { root });
}
private void AddChildrenToNode(CheckableItemViewModel root, IList<CheckableItem> items)
{
foreach(var item in items)
{
var child = new CheckableItemViewModel(item);
var dirItem = item as DirectoryItem; // it's a directory and so it has childs
if(dirItem != null)
{
AddChildrenToNode(child, dirItem.Items);
}
root.Children.Add(child);
}
}
}
And now to my questions:
- How do I connect my
CheckableItemViewModel
to a "kind of" globalCheckableItemModel
? If I inject the constructor by resolving a registered instance (unity container) I've got the problem, that I cannot do that if I'd like to have two ExplorerViews simultanously (or don't I?). - How do I inject if every
CheckableItemViewModel
also needs constructor parameters (is this the case where to use parameter override?) - How do I get a retrieve a list of the actual selected items (or when and where should I update the according model)?
- How do I get a "changed" flag if one of the
CheckableItemViewModel
is altered?
Let me know if i missed a piece of my puzzle.
Thanks for any suggestions.