2011-07-28 2 views
0

기본적으로 C# & WPF를 가르친 후 첫 번째 프로그램에 대한 청구서 알림 프로그램입니다. 사용자가 세부 정보를 입력 한 다음 텍스트 파일에 저장할 수 있습니다. 지금은 나중에 텍스트에서 파일을로드하는 부분을 코딩하려고합니다. StreamReader를 사용하여 텍스트 파일을 ArrayList로 읽은 다음 프로그램에서 ArrayList를 반복하고 DataGrid를 채 웁니다. 뭔가가 작동하지 않습니다, 그리고 난 빈 DataGrid로 끝날거야하지만 올바른 행 번호와 제대로 향하고 열. 문제는 내가 각 ArrayList 위치의 유형을 결정하기 위해 switch-case를 사용하고 그 위치의 내용을 올바른 열에 배치하지만 StreamReader가 모든 것을 문자열로 가져 와서 스위치 케이스를 만드는 것이라고 생각합니다. 무의미한.StreamReader, ArrayList 및 DataGrid가 함께 작업하는 데 도움이 필요합니다.

그래서 기본적으로 내 질문은 어떻게 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

WPF DataGrid를 처음으로 사용하려고하십니까? 너는 용감하다. :) –

+0

나는 그것을 깨닫게 될 것이다. 그러나 그것이 내가 원하는 것을한다. :) –

답변

3

당신이 여기에 게시 한 논리를 잘못 무리가있다. 배열의 각 행에는 StreamReader.ReadLine()이 반환하는 문자열이 포함되어 있습니다. 그것들은 아마도 다른 데이터 유형으로 파싱 될 수있는 문자열 일 수도 있지만 정수 또는 소수가 아니며 문자열입니다.

스위치/케이스 블록은 배열의 모든 요소에 대해 PersonInfo 구조체 (그리드의 행)를 새로 작성합니다. (그리드가 적절한 수의 행을 가지고 있다는 당신의 주장에 놀랐습니다 : 네가 예상하는 행의 수를 4 배로해야하는 것처럼 보입니다.) 또 다른 경우 네 그리드에 같은 네 개의 열을 추가하는 것입니다 다행스럽게도 엘리먼트를 처리 할 때마다 (오류는 발생하지 않지만 불필요하며 데이터 그리드에는 모든 행에 4 개의 열이 아니라 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의 바인딩 정의에 잘못된 항목 (아마도 필드 이름)이 있거나 아마도 해당 컬렉션이 리소스 사전에 올바르게 추가되지 않은 것일 수 있습니다.

+0

도움을 주셔서 감사합니다. 내가 작성한 내용을 엄격히 지키지는 않았지만, 원본을 내가 추가 한 내용과 작업 한 내용을 병합 할 수있었습니다. 감사! –

2

어쨌든, 2011 년 ArrayList를 사용하지 마십시오. 대신 일반 List<T>을 사용하십시오. 아니면 그냥 배열 :

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

상관 개인적으로 클래스로 전환 할 것 :

public class PersonInfo { } 
관련 문제