如何在WPF中添加,保存项目并将其加载到ListView

时间:2019-05-27 13:27:00

标签: wpf vb.net listview binding items

大约两周前,我开始在WPF中进行开发,由于我仅在WinForms中进行开发,因此遇到了常见问题,但设法找到了解决方案。但是,目前,我只能坚持一些东西:将具有多列的项目(通过Visual Basic代码而不是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只是一个目录。

总而言之,专家可以检查我的代码并检查我的操作是否“正确”吗?如果可能,您可以帮助我进行保存和加载过程吗?

谢谢。

1 个答案:

答案 0 :(得分:0)

我刚刚更新了您的结构(我使用了一个类,只是一种习惯),以使用自动属性值,该属性值在VS的最新版本中可用。属性的默认实现与支持者字段一起内置。就像以前一样使用。

您在ObservableCollection上走了正确的路,但是您需要通过添加Even 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

MainWindow XAML

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

歌曲课

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

添加窗口

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

添加窗口XAML

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