简体   繁体   English

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

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

About two weeks ago I started to develop in WPF and, since I only developed in WinForms, I ran into common problems but managed to find the solution for them. 大约两周前,我开始在WPF中开发,因为我只是在WinForms中开发,所以我遇到了常见的问题,但设法找到了解决方案。 However, currently I'm stuck at something: adding items with multiple columns (via visual basic code, not xaml) into a listview. 但是,目前我已经陷入困境:将具有多个列的项目(通过可视化基本代码,而不是xaml)添加到列表视图中。

I'm not sure if it's best to use a Listview or a DataGrid control for this but basically I want the user to be able to add favourite songs to a list, save them to a file and load the file whenever the app is opened. 我不确定是否最好使用Listview或DataGrid控件,但基本上我希望用户能够将喜欢的歌曲添加到列表中,将它们保存到文件并在应用程序打开时加载文件。 The listview currently has three columns: Artist, Song and Status. 列表视图目前有三列:艺术家,歌曲和状态。

When I was programming in WinForms, I used to do this: 当我在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)

Then, to save: 然后,保存:

   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

I've been searching and I've found that I need to use binding so I've tried this: 我一直在寻找,我发现我需要使用绑定,所以我试过这个:

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

And in the XAML listview: 在XAML列表视图中:

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

This works however I'm not sure if this is the WPF-way of doing things. 这可行,但我不确定这是否是WPF的做事方式。

However, I'm stuck at the saving process: 但是,我陷入了保存过程:

 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

This doesn't work. 这不起作用。 Also, PATH_DATABASE is just a directory. 此外,PATH_DATABASE只是一个目录。

To summarise, could an expert review my code and check if I'm doing things "right" and, if possible, could you help me with the saving and loading process? 总而言之,专家是否可以检查我的代码并检查我是否做得“正确”,如果可能的话,您可以帮我保存和加载过程吗?

Thanks. 谢谢。

I just updated your structure (I used a class, just force of habit) to use automatic property values which are available in recent versions of VS. 我刚刚更新了你的结构(我使用了一个类,只是习惯的力量)来使用最新版本的VS中提供的自动属性值。 The default implementation of properties is built in along with the backer fields. 默认的属性实现与backer字段一起构建。 It is used just as before. 它像以前一样使用。

You are on the right track with ObservableCollection but you you need to implement INotifyPropertyChanged by adding the Event PropertyChanged and providing the Sub OnPropertyChanged to raise the event. 您使用ObservableCollection在正确的轨道上,但是您需要通过添加Event PropertyChanged并提供Sub OnPropertyChanged来引发事件来实现INotifyPropertyChanged。

Set up the bindings on the controls and set the ItemsSource ot the ListView to your ObservableList. 在控件上设置绑定,并将ListS的ItemsSource设置为ObservableList。

To save Import System.Text so you can use a StringBuilder. 要保存Import System.Text,以便可以使用StringBuilder。 The loop through the list to build the string to save to a text file. 循环遍历列表以构建保存到文本文件的字符串。

I didn't spend any time trying to make the XAML Windows look nice. 我没有花时间试图让XAML Windows看起来不错。 Pardon the ugliness. 请原谅丑陋。

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

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

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

Add Window XAML 添加窗口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>

EDIT Required Imports 编辑所需的进口

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM