I have recursive ObservableCollection representing directories and files. My idea - if user Checked file, parent directories should know about this.
ViewModel: class that contains Root Collection
public class DirectoryTreeViewModel : BaseViewModel
{
readonly ObservableCollection<DirectoryViewModel> _rootDirectories;
public ObservableCollection<DirectoryViewModel> RootDirectory
{
get { return _rootDirectories; }
}
classes representing Directories and Files
public class DirectoryViewModel: BaseViewModel
{
readonly ObservableCollection<DirectoryViewModel> _childNode;
readonly ObservableCollection<FileViewModel> _childFile;
readonly DirectoryViewModel _parentNode;
readonly Directory _directory;
public DirectoryViewModel(Directory directory)
:this(directory, null)
{
}
private DirectoryViewModel(Directory directory, DirectoryViewModel parentNode)
{
_directory = directory;
_parentNode = parentNode;
_childNode = new ObservableCollection<DirectoryViewModel>();
_childFile = new ObservableCollection<FileViewModel>();
foreach (Directory dir in directory.directories )
{
_childNode.Add(new DirectoryViewModel(dir, this));
}
foreach (File file in directory.files)
{
_childFile.Add(new FileViewModel(file, this));
}
}
public ObservableCollection<DirectoryViewModel> ChildNodes
{
get { return _childNode; }
}
public ObservableCollection<FileViewModel> ChildFiles
{
get { return _childFile; }
}
public ObservableCollection<object> Nodes
{
get
{
ObservableCollection<object> childNodes = new ObservableCollection<object>();
foreach (var dir in this.ChildNodes)
childNodes.Add(dir);
foreach (var file in this.ChildFiles)
childNodes.Add(file);
return childNodes;
}
}
public Directory Directory
{
get => _directory;
}
public string Name
{
get { return _directory.Name; }
}
public string ImageSource
{
get { return _imageSource; }
}
public string Path
{
get { return _directory.Path; }
}
public bool Checked
{
get => _directory.Checked;
set => _directory.Checked = value;
}
public bool hasCheckedFile
{
get => Directory.HasCheckedFile;
set => Directory.HasCheckedFile = value;
}
public bool HasCheckedFile
{
get { return hasCheckedFile; }
set
{
hasCheckedFile = value;
if (_parentNode != null)
_parentNode.hasCheckedFile = hasCheckedFile;
OnPropertyChanged(nameof(HasCheckedFile));
}
}
}
public class FileViewModel: BaseViewModel
{
readonly DirectoryViewModel _parentNode;
readonly File _file;
public FileViewModel(File file, DirectoryViewModel parentNode)
{
_parentNode = parentNode;
_file = file;
}
public string Name
{
get { return _file.Name; }
}
public string ImageSource
{
get { return _imageSource; }
}
public string FullPath
{
get { return _file.FullPath; }
}
public bool Checked
{
get => _file.Checked;
set => _file.Checked=value;
}
public bool IsCheckedToCopy
{
get { return Checked; }
set
{
if (value == true)
{
_parentNode.HasCheckedFile = true;
Checked = true;
}
else if (value == false)
{
Checked = false;
}
_file.Checked = value;
OnPropertyChanged(nameof(IsCheckedToCopy));
}
}
}
}
View
<TreeView x:Name="treeView1" MaxHeight="700" Margin="4,117,-2,-28" ItemsSource="{Binding RootDirectory}" FontSize="12" >
<TreeView.DataContext>
<VM:DirectoryTreeViewModel/>
</TreeView.DataContext>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Nodes}">
<CheckBox x:Name="CopyChBox" IsChecked="{Binding IsCheckedToCopy, Mode=TwoWay}" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Width="20" Margin="1" Source="{Binding ImageSource}"/>
<TextBlock Grid.Column="1" VerticalAlignment="Center" Text="{Binding Name}"/>
</Grid>
</CheckBox>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
If i try to change collection item properties, my root collection "_rootdirectories" (ItemSource for TreeView) does not change. How to implement listener so root collection knows about changes in collection items?
While Binding works well and all data from RooDirectory displayed, If i try to change collection item properties, my root collection "_rootdirectories" (ItemSource for TreeView) does not change. ObservableCollection knows about adding and deleting items, but i don't know how to implement listener so root collection will knew about changes in items properties made from View? Is it possible? Or is it better to use BindingList instead ObservableCollection?