Отделить socket от CPU_name
есть CSV файл, в котором содержатся процессоры, выглядит так:
CPU_name,Socket
Xeon W-2133,LGA 2066
Xeon W-2135,LGA 2066
i7-4820K BOX,LGA 2011
i7-4820K OEM,LGA 2011
нужно отделить Socket от CPU_name, затем вывести их в ComboBox'ы разные. Также нужно, чтобы оно учитывало, что, к примеру, LGA 2066 (содержит такие-то CPU_name), LGA 2011 (содержит такие-то CPU_name), в нашем случае, при выборе в ComboBox1 LGA 2066 выпадает список в ComboBox2 из двух процессоров, при выборе LGA 2011 в ComboBox1 - также выпадает список из 2-ух процессоров в ComboBox2.
Мой код, который просто парсит, в начале код, который загружается при загрузки формы, для добавления в ComboBox спаршенных значений, далее код, который осуществляет парсинг, надеюсь поймете:
// Popitka sozdaniya lista s SocketsIntel;
List<SOCKETintel> socksintel = SOCKETsIntel.GetSOCKETintelValues();
foreach (SOCKETintel sock in socksintel)
{
comboBox12.Items.Add(sock);
}
public static class SOCKETsIntel
{
public static List<SOCKETintel> GetSOCKETintelValues()
{
string filePath = Path.Combine(GetPath + @"\INTEL_CPU\", "INTEL.csv"); // Sdelat' Proverky na nazvanie File;
using (var reader = new StreamReader(filePath))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
var socksintel = new List<SOCKETintel>();
csv.Read();
csv.ReadHeader();
while (csv.Read())
{
var sock = new SOCKETintel
{
CPU_Name = csv.GetField<string>("CPU_name"),
Socket = csv.GetField<string>("Socket")
};
socksintel.Add(sock);
}
return socksintel;
}
}
}
// Sozdanie classa dlya parsinga Type/Brand/Model/Benchmark'a CPU;
public class SOCKETintel
{
public string CPU_Name { get; set; }
public string Socket { get; set; }
public override string ToString() => $"{CPU_Name}";
}
Ответы (1 шт):
Попробуйте такой пример.
Используется привязка данных. Свойство DataSource.
Что именно будет показываться, определяется свойством DisplayMember.
(Ознакомьтесь также со свойством ValueMember.)
Так как оба комбобокса прибиндены к одному источнику данных, то значения в них взаимозависимы. Возможно, вас устроит такое поведение.
using System.Collections.Generic;
using System.Windows.Forms;
namespace WinForms
{
public partial class Form1 : Form
{
private ComboBox comboBoxCPU;
private ComboBox comboBoxSocket;
public Form1()
{
comboBoxSocket = new ComboBox { Parent = this };
comboBoxCPU = new ComboBox { Parent = this, Left = 150 };
var socksintel = new List<SOCKETintel>
{
new SOCKETintel{ CPU_Name = "Xeon W-2133", Socket = "LGA 2066" },
new SOCKETintel{ CPU_Name = "Xeon W-2135", Socket = "LGA 2066" },
new SOCKETintel{ CPU_Name = "i7-4820K BOX", Socket = "LGA 2011" },
new SOCKETintel{ CPU_Name = "i7-4820K OEM", Socket = "LGA 2011" }
};
comboBoxSocket.DisplayMember = nameof(SOCKETintel.Socket);
comboBoxSocket.DataSource = socksintel;
comboBoxCPU.DisplayMember = nameof(SOCKETintel.CPU_Name);
comboBoxCPU.DataSource = socksintel;
}
}
public class SOCKETintel
{
public string CPU_Name { get; set; }
public string Socket { get; set; }
}
}
Можно добиться желаемого поведения кода следующим образом.
Добавим дополнительный класс:
public class Cpu
{
public string Socket { get; set; }
public List<string> Names { get; set; }
}
И используем BindingSource.
var cpus = socksintel
.GroupBy(s => s.Socket, s => s.CPU_Name)
.Select(g => new Cpu { Socket = g.Key, Names = g.ToList() })
.ToList();
var bindingSourceSocket = new BindingSource();
bindingSourceSocket.DataSource = cpus;
comboBoxSocket.DisplayMember = nameof(Cpu.Socket);
comboBoxSocket.DataSource = bindingSourceSocket;
var bindingSourceNames = new BindingSource(bindingSourceSocket, nameof(Cpu.Names));
comboBoxCPU.DataSource = bindingSourceNames;
Трюк здесь в том, что используются два BindingSource. Первый ссылается на коллецию с данными. А второй ссылается на первый, указывая вложенный список.
Ну, если вам привязка данных совсем непонятна, то вот код без неё, с ручным заполнением свойства Items комбобоксов.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace WinForms
{
public partial class Form1 : Form
{
private ComboBox comboBoxCPU;
private ComboBox comboBoxSocket;
private Dictionary<string, object[]> dictionary;
public Form1()
{
comboBoxSocket = new ComboBox { Parent = this };
comboBoxCPU = new ComboBox { Parent = this, Left = 150 };
var socksintel = new List<SOCKETintel>
{
new SOCKETintel {CPU_Name = "Xeon W-2133", Socket = "LGA 2066"},
new SOCKETintel {CPU_Name = "Xeon W-2135", Socket = "LGA 2066"},
new SOCKETintel {CPU_Name = "i7-4820K BOX", Socket = "LGA 2011"},
new SOCKETintel {CPU_Name = "i7-4820K OEM", Socket = "LGA 2011"}
};
dictionary = socksintel
.GroupBy(s => s.Socket, s => (object)s.CPU_Name)
.ToDictionary(g => g.Key, g => g.ToArray());
foreach (var pair in dictionary)
{
comboBoxSocket.Items.Add(pair.Key);
}
comboBoxSocket.SelectedValueChanged +=
ComboBoxSocket_SelectedValueChanged;
}
private void ComboBoxSocket_SelectedValueChanged(object sender, EventArgs e)
{
var socket = (string)comboBoxSocket.SelectedItem;
comboBoxCPU.Items.Clear();
comboBoxCPU.Items.AddRange(dictionary[socket]);
comboBoxCPU.Text = null;
//comboBoxCPU.Text = (string)comboBoxCPU.Items[0];
}
}
public class SOCKETintel
{
public string CPU_Name { get; set; }
public string Socket { get; set; }
}
}
Для наших целей проще всего использовать словарь. Ключом в нём будет название сокета, а значением - массив названий процессоров.
Массив сделан типа object - это позволяет использовать AddRange.
Как создаётся словарь. Сперва данные группируются по названию сокета, затем помещаются в Dictionary.
Если код LINQ непонятен, то срочно его учить! Ныне это основа основ.
В обработчике события очищаем коллекцию Items от предыдущих значений и добавляем новые из словаря.
В завершение нужно очистить свойство Text. Потому что в нём будет предыдущее значение. Как вариант, можно задать ему одно из значений текущей коллекции.

