I am building WPF application where I am using MVVM pattern for data binding and command binding.
When I bind the tree view in a constructor(LoadTreeViewViewModel) it works without any issue but when I do the same in Button Click it is not working. I did a little bit of research where I am also binding to listview and binding is working without issue for listview on button click. So the problem is only with TreeView binding
Below is the complete code for the sample application.
XAML
<Window x:Class="WpfApp1.LoadTreeView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="LoadTreeView" Height="300" Width="300">
<Window.DataContext>
<local:LoadTreeViewViewModel></local:LoadTreeViewViewModel>
</Window.DataContext>
<Window.Resources>
<local:LoadTreeViewViewModel x:Key="viewModel"></local:LoadTreeViewViewModel>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
<RowDefinition Height="1*"></RowDefinition>
</Grid.RowDefinitions>
<TreeView ItemsSource="{Binding Folders}" Grid.Column="0" Grid.Row="0">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Folders}" DataType="{x:Type local:IFolder}">
<TreeViewItem Header="{Binding FolderLabel}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
<ListView VerticalAlignment="Top" Grid.Column="0" Grid.Row="1"
ItemsSource="{Binding Lists, Source={StaticResource viewModel}}">
<ListView.View>
<GridView>
<GridViewColumn/>
</GridView>
</ListView.View>
</ListView>
<Button Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75"
Grid.Column="0" Grid.Row="2"
Command="{Binding LoadSourceCommand, Source={StaticResource viewModel}}"/>
</Grid>
</Window>
LoadTreeView
public partial class LoadTreeView : Window
{
public LoadTreeView()
{
InitializeComponent();
//this.DataContext = new LoadTreeViewViewModel();
}
}
IFolder
public interface IFolder
{
List<IFolder> Folders { get; set; }
string FolderLabel { get; set; }
string FullPath { get; set; }
}
Folder
public class Folder : IFolder
{
public List<IFolder> Folders { get; set; }
public string FolderLabel { get; set; }
public string FullPath { get; set; }
public Folder()
{
Folders = new List<IFolder>();
}
}
LoadTreeViewViewModel
class LoadTreeViewViewModel : INotifyPropertyChanged
{
public LoadTreeViewViewModel()
{
this.LoadSourceCommand = new ViewModel.btnClick(this.LoadData, this.IsValid);
//this.Folders = await LoadDataAsync();
//LoadData();
}
private async void LoadData()
{
this.Folders = await LoadTreeAsync();
this.Lists = await LoadListAsync();
}
private async Task<string[]> LoadListAsync()
{
List<string> temp = new List<string>();
await Task.Delay(TimeSpan.FromSeconds(3)).ConfigureAwait(false);
//add Root items
temp.Add("Dummy1");
temp.Add("Dummy2");
temp.Add("Dummy3");
temp.Add("Dummy4");
return temp.ToArray();
}
private async Task<List<IFolder>> LoadTreeAsync()
{
List<IFolder> temp = new List<IFolder>();
await Task.Delay(TimeSpan.FromSeconds(3)).ConfigureAwait(false);
//add Root items
temp.Add(new Folder { FolderLabel = "Dummy1", FullPath = @"C:\dummy1" });
temp.Add(new Folder { FolderLabel = "Dummy2", FullPath = @"C:\dummy2" });
temp.Add(new Folder { FolderLabel = "Dummy3", FullPath = @"C:\dummy3" });
temp.Add(new Folder { FolderLabel = "Dummy4", FullPath = @"C:\dummy4" });
//add sub items
temp[0].Folders.Add(new Folder { FolderLabel = "Dummy11", FullPath = @"C:\dummy11" });
temp[0].Folders.Add(new Folder { FolderLabel = "Dummy12", FullPath = @"C:\dummy12" });
temp[0].Folders.Add(new Folder { FolderLabel = "Dummy13", FullPath = @"C:\dummy13" });
temp[0].Folders.Add(new Folder { FolderLabel = "Dummy14", FullPath = @"C:\dummy14" });
return temp;
}
private bool IsValid()
{
return true;
}
#region Members
private ViewModel.btnClick loadSourceCommand;
public btnClick LoadSourceCommand
{
get { return loadSourceCommand; }
set { loadSourceCommand = value; }
}
private List<IFolder> m_folders;
public List<IFolder> Folders
{
get { return m_folders; }
set
{
m_folders = value;
NotifiyPropertyChanged("Folders");
}
}
private string[] lists;
public string[] Lists
{
get { return lists; }
set { lists = value; NotifiyPropertyChanged("Lists"); }
}
#endregion
void NotifiyPropertyChanged(string property)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
public event PropertyChangedEventHandler PropertyChanged;
}
btnClick
public class btnClick : System.Windows.Input.ICommand
{
private Action WhatToExecute;
private Func<bool> WhenToExecute;
public btnClick(Action what, Func<bool> when)
{
WhatToExecute = what;
WhenToExecute = when;
}
public void Refresh()
{
if (this.CanExecuteChanged != null)
{
CanExecuteChanged(this, EventArgs.Empty);
}
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return WhenToExecute();
}
public void Execute(object parameter)
{
WhatToExecute();
}
}