0

I am developing an application in WPF in which I want to populate a ListBox on selecting a node of a TreeView. I have populated the TreeView using MVVM pattern. It actually contains the the drives (C:\, D:...) and their corresponding sub-folders. The sub-folders are the nodes. On selecting these nodes the respective files should be shown in the ListBox. I know the C# code to get all the files in a folders, I have also implemented the same. However, I am not getting any clue to map them, so that on selecting the nodes the files in them should get reflected in the ListBox.

Can any please help me in this regard? The application is being developed in MVVM pattern and I need in the same pattern itself.

user3812657
  • 54
  • 1
  • 7

3 Answers3

0

First add a Files collection class to your folder class (used in the tree view)

public class FolderItem
{
    // other class code

    private ObservableCollection<File> _Files = null;

    public ObservableCollection<File> Files
    {
        get
        {
            if (_Files == null) _Files = GetFiles();
            return _Files;
        }
        set
        {
            _Files = value;
        }
    }

}

Then bind the listbox to the selected treeview item.

<ListBox ItemsSource="{Binding ElementName=myTreeView, Path=SelectedItem.Files}"/>
Neil B
  • 2,096
  • 1
  • 12
  • 23
  • I have one more question. Can I ask you if you don't mind. On selecting the directory in the TreeView, the files and getting populating in the list box along with FullPath which is alright. However, another word 'FileName' is getting appended at the beginning. The whole name is appearing in this way FileName: C:\FolderName\FileName.xyz. I need to remove the word 'FileName' from the whole string. Could you please suggest any solution for the same? I'm totally new to WPF, I actually work in web development and started working in WPF recently. Therefore, I'm getting stuck in MVVM pattern. – user3812657 Dec 17 '18 at 12:49
0

You might have quite a number of files and folders so I think I would be inclined to lazy load as much as I could.

That means the viewmodel doesn't need to go iterate through the entire hard drive initially but you need some way of acting when selecteditem changes.

You can't bind selecteditem to a viewmodel because it's read only.

I would therefore use a behaviour like: Data binding to SelectedItem in a WPF Treeview

Bind a SelectedFolder using that. In the setter of SelectedFolder go get the list of folders and files for that folder and fill the two collections. One is the child collection of that selecteditem - for it's folders. The other is an observableCollection for the files to see in the listbox. Make that a propfull and implement inotifyproprtychanged so when I set it to a new collection it notifies the ui. Bind that collection to the itemssource of the listbox.

Andy
  • 11,864
  • 2
  • 17
  • 20
0

Basicly The MVVM pattern uses three Layers :

  1. The Model : Basicly it contains the Model classes and the business logic to get and manipulate Data information.
  2. The ViewModel : It acts as an intermediate layer between the Model and the Views, it is attached to the different views.
  3. The views : The différent views of the app.

Here an example how to fill a Window with list of Drives and Files.

Class BindableBaseViewModel

namespace TalkRepeater.ViewModel
{
    public class BindableBaseViewModel : DependencyObject,INotifyPropertyChanged
    {
        protected virtual void SetProperty<T>(ref T member, T val,[CallerMemberName] string propertyName = null)
        {
           if (object.Equals(member, val)) return;
           member = val;
           PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        protected virtual void OnPropertyChanged(string propertyName)
        {
          PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        public event PropertyChangedEventHandler PropertyChanged = delegate { };

    }
}

Class ViewModel

public  class FoldersControlViewModel : BindableBaseViewModel
{   
        private ObservableCollection<Folders> _listFolders;
    private ObservableCollection<Folders> _listFiles;

        public FoldersControlViewModel()
        {
       FoldersBusinessObject vbo =new FoldersBusinessObject()
            vbo.FillFolders();
        ListFolders = FileBusinessObject.ListFolders;
    }

        public ObservableCollection<Folders> ListFolders
        {
            get
            {
              return _listFolders;
            }
            set
            {
              _listFolders = value;              
              OnPropertyChanged("ListFolders");               
            }
        }

        public ObservableCollection<Folders> ListFiles
        {
            get
            {
              return _listFiles;
            }
            set
            {
              _listFiles = value;              
              OnPropertyChanged("ListFiles");               
            }
        }   

    Public void FillListFiles()
    {
        /*ListFiles= Cod to fill ListFiles*/
    }   
}

Class BusinessObject

public class FoldersBusinessObject
{
     private ObservableCollection<Folders> _ListFolders;

     public void FillFolders()
     {
    /* ListFolders= Code To fill the collection ListFolders   */
     } 

     public ObservableCollection<Folders> ListFolders
     {
            get
            {
               return _ListFolders;
            }
            set
            {
              _ListFolders = value;
            }
        }
}

Foldersview

<Window x:Class="Foldersview"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" 
   d:DesignHeight = "300" Width="1007" Height="606">

    <Grid Margin="10"  >

        <Canvas x:Name="canvasFolders" Margin="-10,0,912,10">
            <TreeView x:Name="TreevFolders" ItemsSource="{Binding Path=ListFolders, Mode=TwoWay}" Canvas.Top="5" Canvas.Left="17" Width="142" Height="561" 
                 SelectedItemChanged="TreevFolders_SelectedItemChanged" >               

                <TreeView.ItemTemplate>
                    <HierarchicalDataTemplate ItemsSource="{Binding Path=ListFolders}">                  
                        <TextBlock Text="{Binding Path=FileName}">    
                        </TextBlock>
                    </HierarchicalDataTemplate>
                </TreeView.ItemTemplate>

            </TreeView>
        </Canvas>

        <Canvas Margin="159,10,0,10">
            <Listview x:Name="Listview1" ItemsSource="{Binding ListFiles, Mode=TwoWay}"  >

            </Listview>
        </Canvas>

    </Grid>

</Window>

Class Foldersview Code Behind

public partial class Foldersview : Window
  {
        private void TreevFolders_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {            
               FoldersControlViewModel vmd = (FoldersControlViewModel)this.DataContext;
               vmd.FillListFiles ();              
        }
}

Class Mainwindow

public class MainWindowViewModel : BindableBase
{
      private FoldersControlViewModel FoldersviewModel;
      public MainWindowViewModel()
      { 
      FoldersviewModel = new FoldersControlViewModel();                  
          Foldersview=new Foldersview();
      Foldersview.Datacontext=FoldersviewModel;
        }      
}

Cordialy

LPGTE SOFTS
  • 120
  • 8