使用 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 模式使用三个层:
- 模型:基本上它包含模型 类 以及获取和操作数据信息的业务逻辑。
- ViewModel:它充当模型和视图之间的中间层,它附加到不同的视图。
- 视图:应用程序的不同视图。
这里是一个如何用驱动器和文件列表填充 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;
}
}
亲切
我正在 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 模式使用三个层:
- 模型:基本上它包含模型 类 以及获取和操作数据信息的业务逻辑。
- ViewModel:它充当模型和视图之间的中间层,它附加到不同的视图。
- 视图:应用程序的不同视图。
这里是一个如何用驱动器和文件列表填充 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;
}
}
亲切