如何以编程方式将多个字符串添加到多列 ListView 中的一行

How to programmatically add multiple strings to one line in a multiple column ListView

所以我是WPF的新手,对WinForms比较熟悉,但是为了绘图性能和好看UI我转用WPF,我没有经验XAML 但我正在解决我的问题。

我有一个 ListView 作为我的媒体播放器应用程序的播放列表。在一行多列中添加多个数据在 WinForms 中不是问题,我只需要添加一个 ListViewItem 并填充它 SubItems ,但在 WPF 中这是一个问题, ListViewItem没有 SubItems 属性 也没有 ListView,我尝试了 Stack Overflow 和其他网站的多个问题,但对我没有帮助,都是关于 DisplayMemberBinding 但是我仍然不能/不知道如何在我的代码中引用它。

XAML 对于 ListView:

<ListView x:Name="Playlist_Main" Margin="0" ItemsSource="{Binding SourceCollection}">
   <ListView.View>
      <GridView>
         <GridViewColumn Header="#" DisplayMemberBinding="{Binding Num}"/>
         <GridViewColumn Header="Title" DisplayMemberBinding="{Binding Title}"/>
         <GridViewColumn Header="Artist" DisplayMemberBinding="{Binding Artist}"/>
         <GridViewColumn Header="Album" DisplayMemberBinding="{Binding Album}"/>
         <GridViewColumn Header="Year" DisplayMemberBinding="{Binding Year}"/>
         <GridViewColumn Header="Track Num" DisplayMemberBinding="{Binding Track}"/>
      </GridView>
   </ListView.View>
</ListView>

主要代码

Playlist_Main.Items.Add(New ListViewItem({Playlist_Main.Items.Count + 1, Info(0), Info(1), Info(2), Info(3), Info(4)}))

您的 ListView / GridView 中的绑定需要一个公开 NumTitle 等属性的项目类型。您必须公开该项目类型的集合并将其分配或绑定到 ItemsSource 属性.

为播放列表中的项目创建模型。如果 属性 值更改,以下示例将实现 INotifyPropertyChanged interface that enables bindings to update through the PropertyChanged 事件。如果您的属性是只读的或者您不需要在运行时更新值,则不必实现它。

public class PlaylistItem : INotifyPropertyChanged
{
   private int _num;
   private string _title;
   private string _artist;
   private string _album;
   private int _year;
   private int _track;

   public PlaylistItem(int num, string title, string artist, string album, int year, int track)
   {
      Num = num;
      Title = title;
      Artist = artist;
      Album = album;
      Year = year;
      Track = track;
   }

   public int Num
   {
      get => _num;
      set
      {
         if (_num == value)
            return;

         _num = value;
         OnPropertyChanged();
      }
   }

   public string Title
   {
      get => _title;
      set
      {
         if (_title == value)
            return;

         _title = value;
         OnPropertyChanged();
      }
   }

   public string Artist
   {
      get => _artist;
      set
      {
         if (_artist == value)
            return;

         _artist = value;
         OnPropertyChanged();
      }
   }

   public string Album
   {
      get => _album;
      set
      {
         if (_album == value)
            return;

         _album = value;
         OnPropertyChanged();
      }
   }

   public int Year
   {
      get => _year;
      set
      {
         if (_year == value)
            return;

         _year = value;
         OnPropertyChanged();
      }
   }

   public int Track
   {
      get => _track;
      set
      {
         if (_track == value)
            return;

         _track = value;
         OnPropertyChanged();
      }
   }

   public event PropertyChangedEventHandler PropertyChanged;

   protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
   {
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
   }
}

在代码隐藏方法中,您可以创建 PlaylistItem 的集合。使用 ObservableCollection<T> that implements the INotifyCollectionChanged interface, if you want to reflect changes to the collection in the user interface, e.g. adding or removing items. The ObservableCollection<T> does that automatically through the CollectionChanged 事件。如果您的列表在运行时未被修改,您可以使用任何其他集合。

var playlistItems = new ObservableCollection<PlaylistItem>();

playlistItems.Add(new PlaylistItem(1, "Enter Sandman", "Metallica", "Metallica", 1991, 1));
// ...add other playlist items.

您可以将此集合直接分配给 ListView,例如在构造函数中。

public MainWindow()
{
   var playlistItems = // ...create the items collection or load them from somewhere.
   Playlist_Main.ItemsSource = playlistItems;
}

另一种方法是在代码隐藏中创建 public 属性。我假设它是 MainWindow.

public partial class MainWindow
{
   public MainWindow()
   {
      PlaylistItems = // ...create the items collection or load them from somewhere.
   }

   public ObservableCollection<PlaylistItem> PlaylistItems { get; }
}

您将在 XAML 中使用 RelativeSource 绑定到 window.

中绑定此集合
<ListView ItemsSource="{Binding Tracks, RelativeSource={RelativeSource AncestorType={x:Type local:MainWindow}}}">

如您所见,方法有很多种,甚至更多。在我看来,最好的方法是使用 MVVM 模式。为此,您将为包含集合的主要 window 创建一个视图模型。

public class MainViewModel : INotifyPropertyChanged
{
   public MainViewModel()
   {
      PlaylistItems = // ...create the items collection or load them from somewhere.
   }

   public ObservableCollection<PlaylistItem> PlaylistItems { get; }

   // ...other properties and methods.
}

接下来,您可以将此视图模型的实例设置为 window 的 DataContext

<Window.DataContext>
   <local:MainViewModel/>
</Window.DataContext>

然后你可以像这样绑定到集合。数据上下文 (MainViewModel) 自动继承。

<ListView ItemsSource="{Binding PlaylistItems}">

此模式可帮助您将用户界面与数据和业务逻辑分开。如您所见,没有从视图模型到视图的引用,只有公开可以绑定的数据的属性。

更多学习资源: