我正在开发一个基本上是账单提醒的程序,主要用于在自学C#& C之后的第一个程序。 WPF。我可以让用户输入详细信息,然后将其保存到文本文件中。我现在正在尝试编写稍后从文本加载文件的部分。我使用StreamReader将文本文件读入ArrayList,然后让程序遍历ArrayList并填充DataGrid。有些东西不起作用,我最终得到一个空白的DataGrid,但是有正确的行数和正确的列。我相信问题是我使用switch-case来确定每个ArrayList位置的类型,然后将该位置的内容放在正确的列中,但StreamReader将所有内容作为字符串拉入,从而制作switch-case没有意义的。
基本上我的问题是,如何让StreamReader将项目置于正确的值类型中,或者甚至是问题?
这是我正在玩的代码。虽然它实际上不是预算计划,但我只是将它作为试验台使用,所以我不会“污染”我的好代码。 :)这些值虽然是完全相同的值类型,但是一旦它工作,它将完成我需要的所有内容并将其传输。
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ArrayList array = new ArrayList();
DataGridTextColumn nameOfPerson = new DataGridTextColumn();
nameOfPerson.Binding = new Binding("name");
DataGridTextColumn ageOfPerson = new DataGridTextColumn();
ageOfPerson.Binding = new Binding("age");
DataGridTextColumn birthdayOfPerson = new DataGridTextColumn();
birthdayOfPerson.Binding = new Binding("birthday");
DataGridTextColumn netWorth = new DataGridTextColumn();
netWorth.Binding = new Binding("netWorth");
using (StreamReader reader = new StreamReader("ArrayListSource.txt"))
{
while (!reader.EndOfStream)
{
array.Add(reader.ReadLine());
}
}
//Array is now populated with contents of text file.
string name;
int age;
DateTime birthday;
decimal value;
//Checks the type of each entry in the array.
for (int i = 0; i < array.Count; i++)
{
System.Type idType = array[i].GetType();
string currentItem = idType.Name;
switch (currentItem)
{
case "String":
name = (string)array[i];
dataGrid1.Items.Add(new PersonInfo() { nameOfPerson = name });
break;
case "Int32":
age = (int)array[i];
dataGrid1.Items.Add(new PersonInfo() { ageOfPerson = age });
break;
case "DateTime":
birthday = (DateTime)array[i];
dataGrid1.Items.Add(new PersonInfo() { birthdayOfPerson = birthday });
break;
case "Decimal":
value = (decimal)array[i];
dataGrid1.Items.Add(new PersonInfo() { netWorth = value });
break;
}
dataGrid1.Columns.Add(nameOfPerson);
dataGrid1.Columns.Add(ageOfPerson);
dataGrid1.Columns.Add(birthdayOfPerson);
dataGrid1.Columns.Add(netWorth);
nameOfPerson.Header = "Name";
ageOfPerson.Header = "Age";
birthdayOfPerson.Header = "Birthdate";
netWorth.Header = "Net Worth";
}
public struct PersonInfo
{
public string nameOfPerson { get; set; }
public int ageOfPerson { get; set; }
public DateTime birthdayOfPerson { get; set; }
public decimal netWorth { get; set; }
}
}
答案 0 :(得分:3)
你在这里发布的逻辑有一堆错误。例如,数组中的每一行都包含一个字符串,因为这是StreamReader.ReadLine()
返回的内容。它们可能是可以想象地被解析为另一种数据类型的字符串,但它们不是整数或小数,它们是字符串。
另一方面,您的switch / case块正在为数组中的每个元素创建一个新的PersonInfo
结构(因而是网格中的一行)。 (我对您的断言网格具有正确的行数感到惊讶;它看起来像它应该具有您期望的行数的4倍。)对于另一个,您将向网格添加相同的四列每次处理元素时(幸运的是,这不会导致错误,但这是不必要的;数据网格只有四列,而不是每行四列)。这些列每个都有一个绑定,但它们的绑定没有来源。
你实际上需要做的很少。在代码中创建绑定是绝望和悲惨的道路。
首先,让我们解析文本文件。您尚未明确文件的格式。设计文件格式的典型方法是使每一行代表一个项目(无论是对象,结构,DataRow
还是你有什么),并且这些行由分隔符分隔成字段。因此,使用垂直条作为分隔符的典型行可能如下所示:
Abner Stoltzfus|36|1975-02-01|12000.00
如果这样做,你可以将每一行拆分成一个数组,然后将结构中的每个字段分配给一个数组元素,例如:
List<PersonInfo> persons = new List<personInfo>();
using (StreamReader sr = new StreamReader(filename))
{
while (!sr.EndOfStream)
{
string line = sr.ReadLine();
string[] fields = line.Split(new char[] { '|' });
PersonInfo p = new PersonInfo
{
Name = fields[0],
Age = int.Parse(fields[1]),
DateOfBirth = DateTime.Parse(fields[2]),
NetWorth = decimal.Parse(fields[3])
});
Debug.WriteLine(string.Format("Name={0}, Age={1}, DateOfBirth={2}, NetWorth={3}",
p.Name, p.Age, p.DateOfBirth, p.NetWorth);
persons.Add(p);
}
}
AddResource("Persons", persons);
那段代码可能有错误 - 我把它写在我的头顶 - 所以你需要修复它,直到你运行它,它可靠地将人员信息写入调试窗口。你应该在开始解决问题的WPF部分之前这样做。
注意代码所做的事情,而不是代码所做的事情,比如创建一个集合来保存所有PersonInfo
结构,并将字符串解析为它们的本机类型。它做的最后一件事是将persons
列表添加到资源字典中(我假设此代码在Window
的代码隐藏中运行;如果没有,则有还有很多其他方法可以做到这一点。)
现在让我们去看你的XAML吧。我对ListView
比DataGrid
更熟悉,所以这就是我将在本例中使用的内容,但是如何使用DataGrid
进行此操作的示例比比皆是。
<ListView ItemsSource="{Binding {DynamicResource Persons}}">
<ListView.View>
<GridView>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="Age" DisplayMemberBinding="{Binding Age}"/>
<GridViewColumn Header="Date of birth" DisplayMemberBinding="{Binding DateOfBirth}"/>
<GridViewColumn Header="Net worth" DisplayMemberBinding="{Binding NetWorth}"/>
</GridView>
</ListView.View>
</ListView>
</ListView>
这将完成您在代码中尝试执行的所有操作:创建控件,告诉它从哪里获取项目,告诉它要显示哪些列,并定义每列的绑定。
以上各种原因可能无法解决,但现在问题被分割了,至少你知道在哪里看。如果调试窗口不包含正确的数据,则从文件读取数据的逻辑中存在错误。如果“输出”窗口包含绑定错误,则XAML中的绑定定义中存在错误(可能是字段名称),或者集合可能未正确添加到资源字典中。
答案 1 :(得分:2)
无论如何,不要,不要在2011年使用ArrayList!请改用通用List<T>
。或者只是一个数组:
string[] lines = System.IO.File.ReadAllLines("ArrayListSource.txt");
我个人会切换到课堂:
public class PersonInfo { }