将对象变量作为字符串传递到 WPF/C# 中的文本框

问题描述 投票:0回答:3

我正在创建一个练习应用程序来练习使用文本文件作为数据库。

  1. 采用管道描绘的文本文件,其中包含 14 个人员数据条目
  2. 在管道上拆分文本文件并将每个条目添加到对象列表中。
  3. 我已将对象列表转换为字符串。

现在我想要单击按钮以在文本框中显示该列表。

这是代码。

namespace StaffRosterLewis.ViewModel
{
    class LoadData
    {
        public static void LoadRosterData()
        {

            
            string mypath = @"J:\zUtilities - Program Files\";
            mypath += "StaffRoster - RosterOld.txt";
            List<Model.Person> people = new List<Model.Person>();
            List<string> lines = File.ReadAllLines(mypath, Encoding.ASCII).ToList();

            foreach (var line in lines)
            {
                string[] entries = line.Split('|');

                Model.Person newPerson = new Model.Person
                {
                    LastName = entries[1],
                    FirstName = entries[2],
                    Extension = entries[3],
                    Department = entries[4],
                    Team = entries[5],
                    Group = entries[6],
                    Title = entries[7],
                    Shift = entries[8],
                    EmergencyResponder = entries[9],
                    AEDCPRCert = entries[10],
                    Languages = entries[11],
                    Notary = entries[12],
                    Note = entries[13],
                    DutyLocation = entries[14]
                };
                //newPerson.Unknown15 = entries[15];

                people.Add(newPerson);


            }
            people.ToString();
            
        }
    }
}

我认为问题出在按钮点击发生的地方。我只是想显示上面的 people 的内容,但是无论我如何尝试引用它,我都会丢失变量“people”。上面的代码是公共的,我将其设置为静态,因此 people 变量应该可以在项目中的任何位置访问。 (我以为)

 private void Button_Show_Click(object sender, RoutedEventArgs e)
        {
            Button_Show.Content = $"{LoadData.LoadRosterData.people.ToString()}";
        }
c# wpf text text-files
3个回答
0
投票

您的代码有很多问题。

您正在尝试在这里访问静态属性之类的方法。

其次,你的返回类型是 void,它应该是 string 类型。

第三,您应该重写 ToString 方法,以所需格式将列表项返回为字符串。

您应该使用

Path.Combine
来获取路径。

如果您计划将

people
设置为静态变量,那么您必须接受它不是线程安全的,并确保在必要时重置它,否则您可能会在列表中遇到意外的项目。

如果一行中的

|
少于 15 个,你的代码将会抛出异常


0
投票

你不需要做

LoadRosterData
static
。但是,正如其他评论者所提到的,该方法必须返回结果(在您当前使用的上下文中)。

  • 因为从文件中读取可能会消耗资源,所以当您将结果存储在例如文件中时,可以提高性能。公共财产

    Peoples

    这允许访问集合而无需强制读取可能未更改的文件。由于这意味着引入一个实例变量,因此建议也将
    LoadRosterData
    设为实例成员。

  • 要从集合中创建字符串,您可以使用

    StringBuilder
    。下面的示例使用
    StringWriter
    ,它允许异步创建字符串。
    StringWriter
    内部也使用
    StringBuilder

  • 您可以通过覆盖 Person 类型的

    ToString
    来进一步改进代码。

  • 为了提高文件读取性能,您应该使用

    StreamReader
    的异步 API,而不是同步
    File
    类。使用
    StreamReader.ReadLineAsync
    还可以节省额外的循环。

  • 为了使文件处理和数据模型创建特别方便,您应该考虑使用序列化。
    推荐的文本格式是 JSON。请参阅 Microsoft Docs:如何在 .NET 中序列化和反序列化(编组和解组)JSON 以了解具体操作方法。反序列化 JSON 文件(最好是异步)将自动生成

    Person
    项目的集合,没有任何麻烦(这将消除丑陋且脆弱的基于索引的访问(以初始化实例属性),并创建任何分隔符,例如管道“|”多余)。

  • 您正在访问从索引“1”开始的数组。但在计算机科学中,索引总是从“0”开始。不确定您是否故意从索引“1”开始。

以下代码修复了一些问题并实现了一些性能改进。它还展示了如何将集合转换为

string
,其中每个
Person
项目都显示在其自己的行中:

PersonDataReader.cs

class PersonDataReader
{
  // Consider to use an ImmutableList to prevent modification.
  // In the current context, this property could (and probably should) defined private.
  public List<Person> Persons { get; }

  // If Person is private, 'HasData' has to be defined private too
  public bool HasData => this.Persons.Any();

  // Constructor
  public PersonDataReader() => this.Persons = new List<Person>();

  public async Task<string> CreateRosterSummaryAsync()
  {
    // Use StringWriter to enable asynchronous string creation.
    // StringWriter also uses a StringBuilder internally to improve performance.
    using (var textWriter = new StringWriter())
    {
      if (!this.HasData)
      {
        await LoadRosterDataAsync();
      }

      // Alternatively use LINQ, 
      // for example Enuemrable.Select together with Enumerable.Aggregate
      // to concatenate the Person.ToString values
      foreach (Person person in this.Persons)
      {
        string personString = person.ToString();

        // Write a Person per line
        await textWriter.WriteLineAsync(personString);
      }

      return textWriter.ToString();
    }
  }

  private async Task LoadRosterDataAsync()
  {
    this.Persons.Clear();

    // Use Path.Combine to ensure a valid formatted path (improve robustness)
    string sourcePath = Path.Combine(@"J:\zUtilities - Program Files", "StaffRoster - RosterOld.txt");

    // Test if the file actually exists to avoid the expensive exception.
    // If the file not found exception is desired, remove the File.Exists condition.
    if (File.Exists(sourcePath))
    {
      return;
    }

    using (var fileReader = new StreamReaeder(sourcePath, Encoding.ASCII))
    {
      while (!fileReader.EndOfFile)
      {
        var line = await reader.ReadLineAsync();
        string[] personValues = line.Split('|', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);

        // If you would use serialization, constructing the type explicitly
        // can be avoided. A recommended text format to allow easy de-/serialization is the JSON format.
        var newPerson = new Model.Person 
        {
          // Check if starting from index '1' is really correct
          LastName = personValues[1],
          FirstName = personValues[2],
          Extension = personValues[3],
          Department = personValues[4],
          Team = personValues[5],
          Group = personValues[6],
          Title = personValues[7],
          Shift = personValues[8],
          EmergencyResponder = personValues[9],
          AEDCPRCert = personValues[10],
          Languages = personValues[11],
          Notary = personValues[12],
          Note = personValues[13],
          DutyLocation = personValues[14]
        };

        this.Persons.Add(newPerson);
      }
    }       
  }
}

Person.cs

class Person
{
  /* Properties of Person */

  // Example text representation of a 'People' object
  // using string interpolation
  public override string ToString()
    => $"Lastname: {this.LastName}; Firstname: {this.FirstName}; Duty location: {this.DutyLocation}"; 
}

MainWindow.xaml.cs

partial class MainWindow : Window
{
  private PersonDataReader PersonDataReader { get; }

  public MainWindow()
  {
    InitializeComponent();

    this.PersonDataReader = new PersonDataReader();
  }

  private async void Button_Show_Click(object sender, RoutedEventArgs e)
  {    
    string personPerLineText = await this.PersonDataReader.CreateRosterSummaryAsync();

    // Why did you chose a Button here? It should be
    // this.DisplayTextBox.Text = personPerLineText;
    this.Button_Show.Content = personPerLineText;

    // Consider to display the complete List<Person> in a ListBox.
  }
}

备注

A

ListBox
可能是显示
Person
列表的更好选择。它的实现更加直观,并且无需担心字符串表示和创建。


-1
投票

你的方法LoadRosterData有一个返回值void,没有任何意义。如果您想返回一个字符串值并使用它,您可以这样做:

//returns a string
public static string MyStringMethod()
{
     string str = "My string";
     //Specify the return value with the return keyword
     return str;
}

或者如果您想返回列表:

public static List<string> MyListMethod()
{
     List<string> list = new List<string>();
     list.Add("one");
     list.Add("two");
     list.Add("three");
     return list;
}

你不能对列表执行ToString(),但你可以引用一个人的索引。 以及用途:

button.Content = $"{MyStringMethod()}"

或者如果你想通过名字获取人,你可以使用 IndexOf() 方法:

List<string> list = new List<string>();
list.Add("one");
list.Add("two");
list.Add("three");

string number = "one";

button.Content = $"{list[list.IndexOf(number)]}";
© www.soinside.com 2019 - 2024. All rights reserved.