使用 MVVM 在 WPF 中选择 TreeView 节点时填充 ListBox

Populate ListBox on Selecting TreeView node in WPF using MVVM

我正在 WPF 中开发一个应用程序,我想在其中填充一个列表框以选择一个 TreeView 的节点。我已经使用 MVVM 模式填充了 TreeView。它实际上包含驱动器(C:\、D:...)及其相应的子文件夹。子文件夹是节点。选择这些节点时,相应的文件应显示在列表框中。我知道获取文件夹中所有文件的 C# 代码,我也实现了相同的代码。但是,我没有得到任何映射它们的线索,因此在选择节点时,它们中的文件应该反映在列表框中。

这方面有什么可以帮助我的吗?该应用程序正在以 MVVM 模式开发,我本身也需要相同的模式。

首先将文件集合 class 添加到您的文件夹 class(在树视图中使用)

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

}

然后将列表框绑定到选定的树视图项。

<ListBox ItemsSource="{Binding ElementName=myTreeView, Path=SelectedItem.Files}"/>

您可能有 qui 一些文件和文件夹,所以我想我会尽可能地延迟加载。

这意味着 viewmodel 最初不需要遍历整个硬盘驱动器,但您需要在所选项目更改时采取某种行动方式。

您不能将 selecteditem 绑定到视图模型,因为它是只读的。

因此,我会使用如下行为: Data binding to SelectedItem in a WPF Treeview

使用它绑定 SelectedFolder。 在 SelectedFolder 的 setter 中,获取该文件夹的文件夹和文件列表并填充两个集合。一个是该选定项目的子集合 - 因为它是文件夹。 另一个是要在列表框中查看的文件的 observableCollection。 使它成为一个 propfull 并实现 inotifyproprtychanged 所以当我将它设置为一个新集合时它会通知 ui。 将该集合绑定到列表框的 itemssource。

基本上 MVVM 模式使用三个层:

  1. 模型:基本上它包含模型 类 以及获取和操作数据信息的业务逻辑。
  2. ViewModel:它充当模型和视图之间的中间层,它附加到不同的视图。
  3. 视图:应用程序的不同视图。

这里是一个如何用驱动器和文件列表填充 Window 的示例。

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

文件夹视图

<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 代码隐藏

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

Class 主窗口

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

亲切