Нужна помощь в совместной работе StreamReader, ArrayList и DataGrid - PullRequest
0 голосов
/ 28 июля 2011

Я работаю над программой, которая, по сути, является напоминанием о счете, в основном для первой программы после того, как я научился C # и WPF. Я могу попросить пользователя ввести данные, а затем сохранить их в текстовом файле. Я сейчас пытаюсь закодировать часть, которая позже загружает файл из текста. Я использовал StreamReader для чтения текстового файла в ArrayList, затем программа перебирала ArrayList и заполняла DataGrid. Что-то не работает, хотя, и я заканчиваю с пустой DataGrid, но с правильным количеством строк и правильно заголовками столбцов. Я полагаю, что проблема в том, что я использую регистр-переключатель, чтобы определить тип каждого местоположения ArrayList, а затем помещаю содержимое этого местоположения в правильный столбец, но StreamReader извлекает все как строку, таким образом делая регистр-переключатель бессмысленно.

Итак, в основном мой вопрос: как заставить 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; }
    }
}

Ответы [ 2 ]

3 голосов
/ 28 июля 2011

Есть куча, которая не так с логикой, которую вы разместили здесь. Во-первых, каждая строка в вашем массиве содержит строку, потому что это то, что возвращает 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, или, возможно, коллекция неправильно добавляется в словарь ресурсов.

2 голосов
/ 28 июля 2011

В любом случае, не используйте ArrayList в 2011 году!Вместо этого используйте общий List<T>.Или просто массив:

string[] lines = System.IO.File.ReadAllLines("ArrayListSource.txt");

Любой лично я бы переключился на класс:

public class PersonInfo { }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...