UWP 10 C#。将文本文件读入一个List <>
让我开始说我是UWP的全新产品,最接近这种语言的是我12年前的C++!UWP 10 C#。将文本文件读入一个List <>
我正在为Windows Universal编写一个应用程序,并且它将逐行阅读不同的文本文件,拆分每行的内容(某些文件不需要拆分行),添加将数据放入列表中,然后在屏幕上显示。我已经尝试了很多方法来做到这一点,但我没有正确地工作。我目前有两种方法正在工作,但并不一致。它会显示数据,但只是有时。当我运行应用程序(在仿真器或本地设备上)时,它可能会或可能不会显示数据,然后如果我点击不同的页面并回到列表页面,它可能会或可能不会再次显示它..
下面的代码。在这种情况下,我拆分文本文件的内容分为3个字符串分割上的“ - ”
我XAML.cs文件
public sealed partial class SPList : Page
{
private List<ThreeColumnList> ThreeColumnLists;
public SPList()
{
this.InitializeComponent();
ThreeColumnLists = ThreeColumnListManager.GetList();
}
}
在我的XAML
<Page
x:Class="TrackingAssistant.SPList"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TrackingAssistant"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:data="using:TrackingAssistant.Model"
mc:Ignorable="d">
<Page.Resources>
<!-- x:DataType="<Name Of Class>" -->
<DataTemplate x:Key="ThreeColumnListDataTemplate" x:DataType="data:ThreeColumnList">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<TextBlock Grid.Column="0" Text="{x:Bind Name}" HorizontalAlignment="Left" FontSize="16" Margin="20,20,20,20" />
<TextBlock Grid.Column="1" Text="{x:Bind Age}" HorizontalAlignment="Left" FontSize="16" Margin="20,20,20,20" />
<TextBlock Grid.Column="2" Text="{x:Bind Job}" HorizontalAlignment="Right" FontSize="16" Margin="20,20,20,20" />
</StackPanel>
</DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="1"
Name="ResultTextBlock"
FontSize="24"
Foreground="Red"
FontWeight="Bold"
Margin="20,20,0,0" />
<!-- ItemsSource="x:Bind <Variable from the CS(Code) Class> -->
<ListView Grid.ColumnSpan="3" ItemsSource="{x:Bind ThreeColumnLists}"
ItemTemplate="{StaticResource ThreeColumnListDataTemplate}">
</ListView>
</Grid>
</Page>
在ThreeColumnList.cs
class ThreeColumnList
{
public string Name { get; set; }
public string Age { get; set; }
public string Job { get; set; }
}
在我ThreeColumnListManager.cs
class ThreeColumnListManager
{
public static List<ThreeColumnList> GetList()
{
var threecolumnlists = new List<ThreeColumnList>();
//Add a dummy row to present something on screen
threecolumnlists.Add(new ThreeColumnList { Name = "Name1", Age = "Age1", Job = "Job1" });
//First working method
readList(threecolumnlists);
//Second Working Method
//tryAgain(threecolumnlists);
return threecolumnlists;
}
public static async void readList(List<ThreeColumnList> tcl)
{
List<ThreeColumnList> a = tcl;
string _line;
var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Lists/splist.txt"));
using (var inputStream = await file.OpenReadAsync())
using (var classicStream = inputStream.AsStreamForRead())
using (var streamReader = new StreamReader(classicStream))
{
while (streamReader.Peek() >= 0)
{
Debug.WriteLine("Line");
_line = streamReader.ReadLine();
//Debug.WriteLine(string.Format("the line is {0}", _line));
string _first = "" + _line.Split('-')[0];
string _second = "" + _line.Split('-')[1];
string _third = "" + _line.Split('-')[2];
a.Add(new ThreeColumnList { Name = _first, Age = _second, Job = _third });
}
}
}
public static async void tryAgain(List<ThreeColumnList> tcl)
{
//Loading Folder
var _folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
_folder = await _folder.GetFolderAsync("Lists");
//Get the file
var _file = await _folder.GetFileAsync("splist.txt");
// read content
IList<string> _ReadLines = await Windows.Storage.FileIO.ReadLinesAsync(_file);
int i = 0;
foreach (var _line in _ReadLines)
{
i++;
string _first = "" + _line.Split('-')[0];
string _second = "" + _line.Split('-')[1];
string _third = "" + _line.Split('-')[2];
tcl.Add(new ThreeColumnList { Name = _first, Age = _second, Job = _third });
}
Debug.WriteLine("Count is " + i);
}
}
在这种情况下与该文件被一分为三,文本文件的样本是这样的
Bloggs, Joe-25-Engineer
Flynn, John-43-Assistant
Sherriff, Patsy-54-Manager
!-!-!
该行! - ! - !是一个分隔线,但它仍然会显示! ! !在屏幕上分裂后 -
最初我试图抓住文件的内容并将它们返回给GetList()并将内容处理到列表中,但我没有运气。
然后我决定尝试将列表传递给抓取内容并在那里填充List的方法。
我所做的两个功能都是在屏幕上显示内容,但并不一致。 ReadList()似乎更频繁地使用tryAgain(),但它每次都不起作用。
此外,只是为了说明,我已经尝试过这种情况,我没有拆分文件每一行的内容,而且我看到的问题只是有时会加载。
I was following this video to get the initial list working。一旦我得到这个工作,然后我开始从文件中读取。
我有一种感觉,我真的很接近,但我不确定。
任何有关我要去哪里的错误建议都是错误的?
谢谢!
尝试实施了用于通知客户INotifyPropertyChanged的和的ObservableCollection接口,通常是结合的客户端,即属性值已更改。
也使用任务来加载数据。
编辑:
MainPage.cs.xaml
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Net.Http;
using System.Net.Sockets;
using System.Threading.Tasks;
using Windows.Foundation.Collections;
using Windows.Storage;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace TestUWP
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
private ObservableCollection<ThreeColumnList> threeColumnLists;
public ObservableCollection<ThreeColumnList> ThreeColumnLists
{
get { return threeColumnLists ?? (threeColumnLists = new ObservableCollection<ThreeColumnList>()); }
set { threeColumnLists = value; }
}
public MainPage()
{
this.InitializeComponent();
LoadData();
}
private async void LoadData()
{
//you can also change the private threeColumnLists to a static
// and do
//if(ThreeColumnLists.Count==0)
// ThreeColumnLists = await ThreeColumnListManager.GetListAsync();
ThreeColumnLists = await ThreeColumnListManager.GetListAsync();
//can also do
// await ThreeColumnListManager.readList(ThreeColumnLists);
}
}
public class ThreeColumnList : INotifyPropertyChanged
{
private string name = string.Empty;
public string Name { get { return name; } set { name = value; NotifyPropertyChanged("Name"); } }
private string age = string.Empty;
public string Age { get { return age; } set { age = value; NotifyPropertyChanged("Age"); } }
private string job = string.Empty;
public string Job { get { return job; } set { job = value; NotifyPropertyChanged("Job"); } }
//PropertyChanged handers
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
}
}
public class ThreeColumnListManager
{
public static async Task<ObservableCollection<ThreeColumnList>> GetListAsync()
{
var threecolumnlists = new ObservableCollection<ThreeColumnList>();
//Add a dummy row to present something on screen
threecolumnlists.Add(new ThreeColumnList { Name = "Name1", Age = "Age1", Job = "Job1" });
//First working method
await readList(threecolumnlists);
//Second Working Method
//tryAgain(threecolumnlists);
return threecolumnlists;
}
public static async Task readList(ObservableCollection<ThreeColumnList> tcl)
{
string _line;
var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Lists/slplist.txt"));
using (var inputStream = await file.OpenReadAsync())
using (var classicStream = inputStream.AsStreamForRead())
using (var streamReader = new StreamReader(classicStream))
{
while (streamReader.Peek() >= 0)
{
Debug.WriteLine("Line");
_line = streamReader.ReadLine();
//Debug.WriteLine(string.Format("the line is {0}", _line));
string _first = "" + _line.Split('-')[0];
string _second = "" + _line.Split('-')[1];
string _third = "" + _line.Split('-')[2];
tcl.Add(new ThreeColumnList { Name = _first, Age = _second, Job = _third });
}
}
}
public static async Task tryAgain(ObservableCollection<ThreeColumnList> tcl)
{
//Loading Folder
var _folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
_folder = await _folder.GetFolderAsync("Lists");
//Get the file
var _file = await _folder.GetFileAsync("splist.txt");
// read content
IList<string> _ReadLines = await Windows.Storage.FileIO.ReadLinesAsync(_file);
int i = 0;
foreach (var _line in _ReadLines)
{
i++;
string _first = "" + _line.Split('-')[0];
string _second = "" + _line.Split('-')[1];
string _third = "" + _line.Split('-')[2];
tcl.Add(new ThreeColumnList { Name = _first, Age = _second, Job = _third });
}
Debug.WriteLine("Count is " + i);
}
}
}
MainPage.xaml中
<Page
x:Class="TestUWP.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestUWP"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<!-- x:DataType="<Name Of Class>" -->
<DataTemplate x:Key="ThreeColumnListDataTemplate" x:DataType="local:ThreeColumnList">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<TextBlock Grid.Column="0" Text="{x:Bind Name}" HorizontalAlignment="Left" FontSize="16" Margin="20,20,20,20" />
<TextBlock Grid.Column="1" Text="{x:Bind Age}" HorizontalAlignment="Left" FontSize="16" Margin="20,20,20,20" />
<TextBlock Grid.Column="2" Text="{x:Bind Job}" HorizontalAlignment="Right" FontSize="16" Margin="20,20,20,20" />
</StackPanel>
</DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="1"
Name="ResultTextBlock"
FontSize="24"
Foreground="Red"
FontWeight="Bold"
Margin="20,20,0,0" />
<!-- ItemsSource="x:Bind <Variable from the CS(Code) Class> -->
<ListView Grid.ColumnSpan="3" ItemsSource="{x:Bind ThreeColumnLists}"
ItemTemplate="{StaticResource ThreeColumnListDataTemplate}">
</ListView>
</Grid>
输出:
谢谢,但我有问题,如果你能帮助。最初我在'SPList.xaml.cs'文件中遇到了问题,但是我发现了一个在线解决方案,将公共ObservableCollection
不要将公共ObservableCollection
我添加了我的完整解决方案与输出检查了这一点,找出你做错了什么。 – Stamos
的肢体,走出这里,但是:
的异步操作意味着它可以在不同的线程中运行,因此它可能是读取文件(ThreeColumnList列表)最终的结果是生活在不同的线。您是否收到(或阻止)加载文件期间或之后发生的异常?您可能会考虑在绑定发生之前重新检查您是否将列表编组到UI线程,如果它的所有者线程不是UI线程以避免此问题。
转移到阅读中,我建议你阅读更多有关'async \ await'的内容。 –
你必须await
或Wait()
在Task
。从public static async void readList(List<ThreeColumnList> tcl)
更改签名public static async Task readList(List<ThreeColumnList> tcl)
并调用它像readList(threecolumnlists).Wait();
这打破你的代码的不同步性,但会奏效。 最好的办法是改变GetList()
是异步和任务运行此展示给用户微调或进度条:
public SPList()
{
this.InitializeComponent();
Task.Run(async() =>
{
IsLoading = true;
ThreeColumnLists = await ThreeColumnListManager.GetList();
IsLoading = false;
}
}
private bool _isLoading;
public bool IsLoading
{
get { return _isLoading; }
set
{
if(_isLoading != value)
{
_isLoading = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsLoading));
}
}
}
谢谢。 首先我试着用'.Wait()'方法。当我试图在这个改变后运行应用程序时,一旦我点击按钮来加载文件,它就会挂起。 然后我按照你的建议更改了'GetList()',这样工作起来更好。但它每次都不会加载。它将成功加载大约80%的时间,这是一个巨大的改进。 'PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(nameof(IsLoading));'在'PropertyChanged?'的代码中显示一个异常,所以现在我已经评论了这一点。时间?? 谢谢! – microbenny
另外,我刚刚注意到,当数据没有完全加载,它甚至没有显示虚拟行被编码到屏幕上的列表中。所以它几乎像现在似乎有一个问题与清单,但不是文本文件!... – microbenny
对于'PropertyChanged'工作,你的类需要实现'INotifyPropertyChanged'接口。 –
可以显示(的一部分)输入文件? – Sybren
@sybren对不起,是的!我曾打算补充一点!我已经用示例更新了帖子。我也尝试过这种方式,我没有将文件中的每一行都分开,我只使用一列,并且只在有时候才有效。该文本文件中的数据就像任何带有新行的文本文件一样。谢谢! – microbenny
我调试你的代码并且工作正常。我相信你的代码部分很好。令我担心的是xaml部分。你如何展示你的数据?你可以添加xaml部分以及如何传递元素中的数据? – Stamos