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

o2gm4chl  于 2022-12-14  发布在  C#
关注(0)|答案(3)|浏览(187)

我正在创建一个练习应用程序,以练习将文本文件用作数据库。
1.以竖线分隔的文本文件为例,该文件包含14个人员数据条目
1.拆分文本文件中的管道,并将每个条目添加到一个对象列表中(大约150个)。
1.我已经将对象列表转换为字符串。
现在我想要一个按钮,单击它可以在文本框中显示该列表。
下面是代码。

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()}";
        }
zf9nrax1

zf9nrax11#

您的程式码有许多问题。
您正在尝试存取类似静态属性的方法。
第二,返回类型为void,它应该是string类型。
第三,您应该重写ToString方法,以所需格式将列表项作为字符串返回。
您应该使用Path.Combine来获取路径。
如果你打算把people作为静态变量,那么你必须接受它不是线程安全的,并确保在必要的时候重置它,否则你可能会在列表中遇到意想不到的项目。
如果一行中的|少于15个,则代码将引发异常

yshpjwxd

yshpjwxd2#

你不需要使用LoadRosterDatastatic,但是,正如其他评论者所提到的,该方法必须返回一个结果(在你当前使用的上下文中)。

  • 由于从文件阅读可能会消耗大量资源,因此将结果存储在公共属性(例如Peoples)中可以提高性能。

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

  • 若要从集合建立字串,您可以使用StringBuilder。下列范例使用StringWriter,它允许异步建立字串。StringWriter也会在内部使用StringBuilder
  • 您可以通过重写Person类型的ToString来进一步改进代码。
  • 为了提高文件阅读性能,您应该使用StreamReader的异步API,而不是同步的File类。使用StreamReader.ReadLineAsync还可以保存额外的循环。
  • 为了使文件处理和数据模型创建更加方便,您应该考虑使用序列化。

推荐的文本格式是JSON。请参阅Microsoft Docs: How to serialize and deserialize (marshal and unmarshal) JSON in .NET了解如何操作。反序列化JSON文件(最好是异步)将自动生成Person项的集合,而不会有任何麻烦(这将消除丑陋和脆弱的基于索引的访问(初始化示例属性),以及使任何像管道'|“多余)。

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

下面的代码修复了一些问题并实现了一些性能改进。它还演示了如何将集合转换为string,其中每个Person项都显示在其自己的行中:

个人数据读取器.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);
      }
    }       
  }
}

人员.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}"; 
}

主窗口.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.
  }
}

备注

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

hmtdttj4

hmtdttj43#

您的方法 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() 处理list,但是你可以引用一个人的索引。用法:

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)]";

相关问题