如何在 WPF 中将项目添加、保存和加载到列表视图

How do I add, save and load items to a listview in WPF

大约两周前,我开始在 WPF 中进行开发,由于我只在 WinForms 中进行开发,因此我 运行 遇到了常见问题,但设法找到了解决方案。但是,目前我遇到了一些问题:将具有多列的项目(通过可视化基本代码,而不是 xaml)添加到列表视图中。

我不确定是否最好为此使用 Listview 或 DataGrid 控件,但基本上我希望用户能够将喜欢的歌曲添加到列表中,将它们保存到文件中并在任何时候加载文件该应用程序已打开。列表视图目前有三列:艺术家、歌曲和状态。

当我在 WinForms 中编程时,我曾经这样做过:

        Dim Song As New ListViewItem
        Form1.ListView1.Items.Add(Song)
        Song.Text = TextBox1.Text
        Song.SubItems.Add(TextBox2.Text)
        Song.SubItems.Add(TextBox3.Text)

然后,保存:

   Dim Song As New ListViewItem
            Form1.ListView1.Items.Add(Song)
            Song.Text = TextBox1.Text
            Song.SubItems.Add(TextBox2.Text)
            Song.SubItems.Add(TextBox3.Text)
            Try
                Dim myWriter As New IO.StreamWriter(PATH_DATABASE)
                For Each myItem As ListViewItem In Form1.ListView1.Items
                    myWriter.WriteLine(myItem.Text & "|" & myItem.SubItems(1).Text & "|" & myItem.SubItems(2).Text & "|" & myItem.SubItems(3).Text
                Next
                myWriter.Close()
            Catch ex As Exception
                MsgBox("Error: " & ex.Message, vbCritical, "Error")
            End Try

我一直在搜索,发现我需要使用绑定,所以我尝试了这个:

Imports System
Imports System.Collections.Generic
Imports System.Collections.ObjectModel
Imports System.Windows


Public Structure Song

    Public _artist As String
    Public _title As String
    Public _status As String

    Property Artist() As String
        Get
            Return _artist
        End Get
        Set(ByVal Value As String)
            _artist = Value
        End Set
    End Property
    Property Title() As String
        Get
            Return _title
        End Get
        Set(ByVal Value As String)
            _title = Value
        End Set
    End Property
    Property Status() As String
        Get
            Return _status
        End Get
        Set(ByVal Value As String)
            _status = Value
        End Set
    End Property
End Structure



Public Class WINDOW_AddSong

    Dim songs As New ObservableCollection(Of Song)




    Private Sub Button1_Click(sender As Object, e As RoutedEventArgs) Handles Button1.Click
        Dim Song As New ListViewItem

        For Each wnd As Window In Application.Current.Windows
            If wnd.GetType Is GetType(MainWindow) Then

                DirectCast(wnd, MainWindow).Listview1.Items.Add(Alimento)
                Alimento.Content = New Song() With {._artist = "Lol", ._title = "Lol2", ._status = "Lol3"}




            End If
        Next
    End Sub
End Class

并且在 XAML 列表视图中:

<GridViewColumn Header="Artist" DisplayMemberBinding="{Binding Artist}"/>
<GridViewColumn Header="Title" DisplayMemberBinding="{Binding Title}"/>
<GridViewColumn Header="Status" DisplayMemberBinding="{Binding Status}"/>

这可行,但我不确定这是否是 WPF 的处理方式。

但是,我卡在了保存过程中:

 Try
            Dim myWriter As New IO.StreamWriter(PATH_DATABASE)
            For Each wnd As Window In Application.Current.Windows
                If wnd.GetType Is GetType(MainWindow) Then
                    For Each myItem As ListViewItem In DirectCast(wnd, MainWindow).Listview1.Items
                        myWriter.WriteLine(Song, Artist, Status)
                    Next
                End If
            Next
            myWriter.Close()
        Catch ex As Exception
            MsgBox("Error: " & ex.Message, vbCritical, "Error")
        End Try

这行不通。 此外,PATH_DATABASE 只是一个目录。

总结一下,专家能否检查我的代码并检查我是否在做事情"right",如果可能的话,你能帮我完成保存和加载过程吗?

谢谢。

我刚刚更新了您的结构(我使用了 class,只是出于习惯)以使用自动 属性 值,这些值在最新版本的 VS 中可用。属性的默认实现与支持者字段一起内置。它和以前一样使用。

ObservableCollection 的方向正确,但您需要通过添加 Event PropertyChanged 并提供 Sub OnPropertyChanged 来引发事件来实现 INotifyPropertyChanged。

在控件上设置绑定并将 ListView 的 ItemsSource 设置为您的 ObservableList。

保存 Import System.Text 以便您可以使用 StringBuilder。循环遍历列表以构建要保存到文本文件的字符串。

我没有花任何时间尝试使 XAML Windows 看起来不错。丑请见谅

Class MainWindow
    Public Songs As New ObservableCollection(Of Song)

    Protected Sub OnLoad(sender As Object, e As RoutedEventArgs)
        Songs.Add(New Song("Nirvana", "Smells Like Teen Spirit", "Open"))
        Songs.Add(New Song("John Lennon", "Imagine", "In Stock"))
        Songs.Add(New Song("U2", "One", "Unknown"))
        Songs.Add(New Song("Michael Jackson", "Billie Jean", "Open"))
        lvSongs.ItemsSource = Songs
    End Sub

    Private Sub BtnAdd_Click(sender As Object, e As RoutedEventArgs)
        Dim frm As New frmAdd
        frm.mainForm = Me 'send the instance of the current form to the new form
        frm.ShowDialog()
    End Sub

    Private Sub SaveList()
        Dim sb As New StringBuilder
        For Each item As Song In Songs
            sb.AppendLine($"{item.Artist}|{item.Title}|{item.Status}")
        Next
        'call sb.ToString and write it to a .txt file
    End Sub
End Class

主要WindowXAML

<Window x:Class="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:WPF_BindComboBox"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid Loaded="OnLoad"
          Name="root">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>

        </Grid.RowDefinitions>
        <ListView Margin="10" Name="lvSongs" Grid.Row="0">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <WrapPanel>
                        <TextBlock Text="Name: " />
                        <TextBox x:Name="txtArtist" 
                                 Text="{Binding Artist, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
                                 FontWeight="Bold"/>
                        <TextBlock Text=", " />
                        <TextBlock Text="Age: " />
                        <TextBox Text="{Binding Title}" 
                                 FontWeight="Bold" />
                        <TextBlock Text=" (" />
                        <TextBox Text="{Binding Status}"  />
                        <TextBlock Text=")" />
                    </WrapPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        <Button x:Name="btnAdd" Grid.Row="1" Height="25" Width="100" Content="Add a Song" Click="BtnAdd_Click"/>      
    </Grid>
</Window>

歌曲class

Public Class Song
    Implements INotifyPropertyChanged

    Public Property Artist() As String
    Public Property Title() As String
    Public Property Status() As String

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

    Protected Sub OnPropertyChanged(ByVal name As String)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(name))
    End Sub

    Public Sub New(art As String, Ttl As String, Stat As String)
        Artist = art
        Title = Ttl
        Status = Stat
    End Sub
End Class

添加Window

Public Class frmAdd

    Public mainForm As MainWindow

    Private Sub BtnAdd_Click(sender As Object, e As RoutedEventArgs)
        mainForm.Songs.Add(New Song(txtArtist.Text, txtTitle.Text, txtStatus.Text))
        ClearForm()
    End Sub

    Private Sub ClearForm()
        txtArtist.Clear()
        txtTitle.Clear()
        txtStatus.Clear()
    End Sub

End Class

添加WindowXAML

<Window x:Class="frmAdd"
        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:WPF_BindComboBox"
        mc:Ignorable="d"
        Title="frmAdd" Height="172.641" Width="307.547">
    <Grid >
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Column="0" Grid.Row="0" Text="Artist" FontSize="16" FontWeight="Bold"/>
        <TextBox x:Name="txtArtist" Grid.Column="1" Grid.Row="0" FontSize="16" Width="150" />
        <TextBlock Grid.Column="0" Grid.Row="1" Text="Title" FontSize="16" FontWeight="Bold"/>
        <TextBox x:Name="txtTitle" Grid.Column="1" Grid.Row="1" FontSize="16" Width="150"/>
        <TextBlock Grid.Column="0" Grid.Row="2" Text="Status" FontSize="16" FontWeight="Bold"/>
        <TextBox x:Name="txtStatus" Grid.Column="1" Grid.Row="2" FontSize="16" Width="150"/>
        <Button x:Name="btnAdd" Grid.Column="1" Grid.Row="4" Content="Add Song" Click="BtnAdd_Click"/>
    </Grid>
</Window>

编辑 需要进口

Imports System.Collections.ObjectModel
Imports System.ComponentModel
Imports System.Text