简体   繁体   English

ListView WPF中的Sum列

[英]Sum Columns in ListView WPF

I have the below csv file: 我有以下csv文件:

Name,Score
Kelly,5
James,5
Sara,1
Kelly,4
James,1
John,3

And I am trying to read the CSV file, get the sum of the Scores based on the Names and load them into the listview. 我正在尝试读取CSV文件,根据名称获取得分总和并将其加载到列表视图中。

As a start, I was able to read the CSV file and load it into two listviews for each column. 首先,我能够读取CSV文件并将其加载到每列的两个列表视图中。 below is my code: 下面是我的代码:

   public MainWindow()
    {
        InitializeComponent();      
        using (var fs = File.OpenRead(filepath))
        using (var reader = new StreamReader(fs))
        {
            List<string> list0 = new List<string>();
            List<string> list1 = new List<string>();
            while (!reader.EndOfStream)
            {
                var line = reader.ReadLine();
                var values = line.Split(',');

                list0.Add(values[0]);
                list1.Add(values[1]);
                 //sum = list1.Sum(x => Convert.ToInt32(x));
            }

            List0.ItemsSource = list0;
            List1.ItemsSource = list1; 

         }
  }

and here's the xaml code I used: 这是我使用的xaml代码:

    <ListView Name="List0" HorizontalAlignment="Left" Height="258" Margin="0,33,0,0" VerticalAlignment="Top" Width="267" >
            <ListView.View>
                <GridView>
                    <GridViewColumn DisplayMemberBinding="{Binding}"/>
                </GridView>
            </ListView.View>
        </ListView>
        <ListView Name="List1" HorizontalAlignment="Left" Height="258"   Margin="272,33,0,0" VerticalAlignment="Top" Width="172" >
            <ListView.View>
                <GridView>
                    <GridViewColumn DisplayMemberBinding="{Binding}"/>
                </GridView>
            </ListView.View>
        </ListView>

And this is working fine with me. 这对我很好。 But I got stuck from here and I was wondering if it's possible to get the sum of the Score column based on the Names in the listview. 但我被困在这里,我想知道是否有可能根据列表视图中的名称得到分数列的总和。

For example, get the total score of Kelly, get the total score of James etc. So the listview would look like this: 例如,获得Kelly的总分,得到James等的总分。所以listview看起来像这样:

Name,Score
Kelly,9 
James,6 
Sara,1
John,3

I tried to use the Sum option and thought of printing it to a label to test, but it didn't work and i got an error saying "Input string was not in a correct format" 我尝试使用Sum选项,并考虑将其打印到标签进行测试,但它没有工作,我收到一条错误,说“输入字符串格式不正确”

I am still not that experienced in C#, WPF and XAML; 我仍然没有C#,WPF和XAML的经验; especially in reading and parsing CSV files so I am not sure how to go about this. 特别是在阅读和解析CSV文件时,我不知道如何解决这个问题。 Any help in this matter or pointers is much appreciated! 非常感谢您对此事或指针的任何帮助! Thank you! 谢谢!

I'd use a Dictionary: 我使用字典:

public MainWindow()
{
    InitializeComponent();      
    using (var fs = File.OpenRead(filepath))
    using (var reader = new StreamReader(fs))
    {
        var dict = new Dictionary<string, int>();
        while (!reader.EndOfStream)
        {
            var line = reader.ReadLine();
            var values = line.Split(',');

            // Discard header line
            if (("Name" == values[0]) && ("Score" == values[1]))
                continue;

            if (dict.ContainsKey(values[0]))
                dict[values[0]] += Convert.ToInt32(values[1]);
            else
                dict[values[0]] = Convert.ToInt32(values[1]);
        }

        // Now you can create some lists to display
        var list0 = new List<string>();
        var list1 = new List<string>();
        foreach (KeyValuePair<string, string> entry in dict)
        {
            list0.Add(entry.Key);
            list1.Add(entry.Value.ToString());
        }

        List0.ItemsSource = list0;
        List1.ItemsSource = list1; 
     }
}

I would create a new class for storing the persons including their score. 我会创建一个新的类来存储人员,包括他们的分数。 Something like this 像这样的东西

public class Person
{
    public string Name { get; private set; }
    public int Score { get; set; }

    public Person(string name, int score)
    {
        Name = name;
        Score = Score;
    }
}

Then you could change your logic to something like this 然后你可以把你的逻辑改成这样的东西

var lines = File.ReadAllLines(filepath);
var persons = new List<Person>();

foreach(var line in lines)
{
    var values = line.Split(',');
    var name = values[0];
    var score = int.Parse(line[1].ToString());

    var person = persons.FirstOrDefault(x => x.Name == name);
    if(person == null)
    {
        var newPerson = new Person(name, score);
        persons.Add(newPerson);
    }
    else
    {
        person.Score += score;
    }
}

Advantage of a Person class is a cleaner and more understandable code; Person类的优点是更清晰,更易理解的代码; no magic strings where nobody knows what their value means. 没有魔法字符串,没人知道它们的价值意味着什么

In your logic you can raise the score of a person when you already have one entry for the person in your list. 在您的逻辑中,当您已为列表中的人员输入一个条目时,您可以提高某人的分数。

//edit Binding to xaml You can use a DataGrid for example. //编辑绑定到xaml例如,您可以使用DataGrid

<DataGrid ItemsSource="{Binding Persons}" />

Persons is the ObservableCollection<Person> in your ViewModel. Persons是ViewModel中的ObservableCollection<Person> The DataGrid will automatically create one column for every property in your Person class. DataGrid将自动为Person类中的每个属性创建一列。 You could custommize your DataGrid to get the look you want. 您可以自定义DataGrid以获得所需的外观。 There are alot of examples in the internet. 互联网上有很多例子。

//edit Binding The collection with the persons has to be public. //编辑绑定包含人员的集合必须是公开的。 Otherwise you could not access it from the xaml. 否则你无法从xaml访问它。

You could remove 你可以删除

var persons = new List<Person>();

And replace it with a property in your MainWindow class. 并将其替换为MainWindow类中的属性。

public ObservableCollection<Person> Persons {get; set;}

You class should look like 你的课应该是这样的

public ObservableCollection<Person> Persons {get; set;}

public MainWindow()
    {
        InitializeComponent();

        var lines = File.ReadAllLines(filepath);
        Persons = new ObservableCollection<Person>();

And in your DataGrid change the binding to ItemsSource="{Binding Persons}" 并在您的DataGrid更改绑定到ItemsSource="{Binding Persons}"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM