0

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();
    }
}

1 Answer 1

1

You likely have a binding error. Check the output log for and BindingExpression errors.

I suspect you want to use viewModel instance you've defined, rather than the window's datacontext, because they're going to be two different instances.

<TreeView ItemsSource="{Binding Folders, Source={StaticResource viewModel}}"
          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>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.