2017-05-06 155 views
2

我想問一下如何使用MVVM模式填充listview我是mvvm模式的初學者,我從閱讀中學到了更多的東西。我在使用wpf之前完成了這個,但是我使用了後面的代碼。使用mvvm填充列表視圖

我使用Mvvm Light。我要的是瀏覽文件夾的位置,然後填充文件的列表視圖裏面

到目前爲止,我已經有一個瀏覽文件夾

我有這樣的代碼

public class OpenFileDialogVM : ViewModelBase 
    { 
     public static RelayCommand OpenCommand { get; set; } 
     private string _selectedPath; 
     public string SelectedPath 
     { 
      get { return _selectedPath; } 
      set 
      { 
       _selectedPath = value; 
       RaisePropertyChanged("SelectedPath"); 
      } 
     } 

     private string _defaultPath; 

     public OpenFileDialogVM() 
     { 
      RegisterCommands(); 
     } 

     public OpenFileDialogVM(string defaultPath) 
     { 
      _defaultPath = defaultPath; 
      RegisterCommands(); 
     } 

     private void RegisterCommands() 
     { 
      OpenCommand = new RelayCommand(ExecuteOpenFileDialog); 
     } 

     private void ExecuteOpenFileDialog() 
     { 
      var dialog = new FolderBrowserDialog(); 
      dialog.ShowDialog(); 

      SelectedPath = dialog.SelectedPath; 
     } 
    } 

和我有這個用於用戶控制的代碼

<UserControl x:Class="MvvmLight1.FolderDialog" 
      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" 
      xmlns:vm="clr-namespace:MvvmLight1" 
      xmlns:local="clr-namespace:MvvmLight1" 
      mc:Ignorable="d" d:DesignWidth="300" Height="186.916" > 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="90*"/> 
      <RowDefinition Height="97*"/> 
     </Grid.RowDefinitions> 
     <Grid> 
      <TextBox Text="{Binding SelectedPath}" /> 
     </Grid> 
     <Grid Grid.Row="1" > 
      <Button Command="vm:OpenFileDialogVM.OpenCommand" >Browse</Button> 
     </Grid> 

    </Grid> 
</UserControl> 

到目前爲止瀏覽正在工作。我的問題是我怎樣才能調用這段代碼。選擇文件夾後,我可以填充我的列表視圖?

private void Call(string selectedpath) 
     { 
      try 
      { 
       var allFiles = Directory.GetFiles(selectedpath, "*", SearchOption.AllDirectories); 

       foreach (var item in allFiles) 
       { 
        System.Console.WriteLine(item); 
        //code for populating listview 
       } 
      } 
      catch (System.Exception ex) 
      { 
       System.Console.WriteLine(ex.StackTrace); 
       throw ex; 
      } 
     } 

謝謝你的時間。

+0

注:System.Windows.Forms的 –

+0

是添加引用。你可以幫我或給我一些代碼片段如何使用MVVM調用代碼?在我選擇了一個文件夾之後謝謝 – classname13

+0

現在在我的IDE中重現。有關如何撰寫問題的內容,請參閱[MCVE](https://stackoverflow.com/help/mcve)以供將來參考(儘管如此,這是一項相當不錯的工作)。 –

回答

1
  • 使文件成爲公共可觀察集合。
  • 引發PropertyChanged事件。
  • 將窗口的datacontext設置爲您的視圖模型。
  • 綁定到xaml中的viewmodel屬性。

CS

using System; 
    using System.ComponentModel; 
    using System.IO; 
    using System.Windows; 
    using System.Windows.Input; 
    using System.Collections.ObjectModel; 

    namespace StackOverflow_PopulateListView 
    { 
     /// <summary> 
     /// Interaction logic for MainWindow.xaml 
     /// </summary> 
     public partial class MainWindow : Window 
     { 
      public MainWindow() 
      { 
       InitializeComponent(); 
       DataContext = new OpenFileDialogVM(); 
      } 
     } 

     public class OpenFileDialogVM : ViewModelBase 
     { 
      public static RelayCommand OpenCommand { get; set; } 
      private string _selectedPath = "Enter a Path"; 
      public string SelectedPath 
      { 
       get { return _selectedPath; } 
       set 
       { 
        _selectedPath = value; 
        OnPropertyChanged("SelectedPath"); 
       } 
      } 

      private ObservableCollection<string> _files = new ObservableCollection<string>() { "Tits", "balls", "ass", "tits" }; 
      public ObservableCollection<string> Files 
      { 
       get { return _files; } 
       set 
       { 
        _files = value; 
        OnPropertyChanged("Files"); 
       } 
      } 

      private ICommand _selectFileCommand; 
      public ICommand SelectFileCommand 
      { 
       get 
       { 
        return _selectFileCommand ?? (_selectFileCommand = new RelayCommand(() => Call(SelectedPath))); 
       } 
       protected set 
       { 
        _selectFileCommand = value; 
       } 
      } 

      public void Call(string selectedpath) 
      { 
       try 
       { 
        Files = new ObservableCollection<string>(Directory.GetFiles(selectedpath, "*", SearchOption.AllDirectories)); 
       } 
       catch (Exception ex) 
       { 
        Console.WriteLine(ex.StackTrace); 
        throw ex; 
       } 
      } 
     } 

     public class RelayCommand : ICommand 
     { 
      public Action Act { get; set; } 

      /// <summary> Occurs when the target of the Command should reevaluate whether or not the Command can be executed. </summary> 
      public event EventHandler CanExecuteChanged; 

      public RelayCommand(Action act) 
      { 
       Act = act; 
      } 

      /// <summary> Returns a bool indicating if the Command can be exectued with the given parameter </summary> 
      public bool CanExecute(object obj) 
      { 
       return true; 
      } 

      /// <summary> Send a ICommand.CanExecuteChanged </summary> 
      public void ChangeCanExecute() 
      { 
       object sender = this; 
       EventArgs eventArgs = null; 
       CanExecuteChanged(sender, eventArgs); 
      } 

      /// <summary> Invokes the execute Action </summary> 
      public void Execute(object obj) 
      { 
       Act(); 
      } 
     } 

     /// <summary> 
     /// Extremely generic ViewModelBase; for copy-pasting into almost any MVVM project 
     /// </summary> 
     public class ViewModelBase : INotifyPropertyChanged 
     { 
      public event PropertyChangedEventHandler PropertyChanged; 

      /// <summary> 
      /// Fires PropertyChangedEventHandler, for bindables 
      /// </summary> 
      protected virtual void OnPropertyChanged(string name) 
      { 
       PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); 
      } 

     } 
    } 

XAML

<Window x:Class="StackOverflow_PopulateListView.MainWindow" 
    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:StackOverflow_PopulateListView" 
    mc:Ignorable="d" 
    Title="MainWindow" Height="350" Width="525" 
    > 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="8*"/> 
      <RowDefinition Height="1*"/> 
      <RowDefinition Height="1*"/> 
     </Grid.RowDefinitions> 

     <ListView ItemsSource="{Binding Files}" Grid.Row="0"> 
      <ListView.ItemTemplate> 
       <DataTemplate> 
        <TextBlock Text="{Binding}"/> 
       </DataTemplate> 
      </ListView.ItemTemplate> 
     </ListView> 

     <TextBox Grid.Row="1" 
        Text="{Binding SelectedPath}" 
       /> 

     <Button Grid.Row="2" 
        Content="Call" 
        Command="{Binding SelectFileCommand}" 
       /> 

    </Grid> 
</Window> 
+0

我只是將問題歸結爲「將xaml listview數據綁定到viewmodel中的文件屬性」。這包括獨立編譯所需的一切。祝你好運! –

+0

謝謝你的工作。而現在我只需要搜索那些代碼是什麼以及何時使用它們。非常感謝你 – classname13

1

您的視圖模型應該有文件名的ObservableCollection

public ObservableCollection<string> FileNames { get; } 
    = new ObservableCollection<string>(); 

當選擇一個目錄,其填充:

var files = Directory.EnumerateFiles(selectedpath, "*", SearchOption.AllDirectories); 

FileNames.Clear(); 

foreach (var file in files) 
{ 
    FileNames.Add(file); 
} 

你會那麼ListBox的ItemsSource屬性綁定到該集合:

<ListBox ItemsSource="{Binding FileNames}"/> 
+0

。何時以及如何使用mvvm模式調用該代碼?當您選擇一個目錄時,「即使SelectedPath屬性發生變化,您也會非常感謝 – classname13

+0

」。 – Clemens