169 lines
7.2 KiB
C#
169 lines
7.2 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.ComponentModel;
|
||
using System.Data;
|
||
using System.Drawing;
|
||
using System.Linq;
|
||
using System.Reflection;
|
||
using System.Text;
|
||
using System.Text.RegularExpressions;
|
||
using System.Threading.Tasks;
|
||
using System.Windows.Forms;
|
||
|
||
namespace Components
|
||
{
|
||
public partial class ListBoxMany : UserControl
|
||
{
|
||
private string _templateString;
|
||
private string __startSymbol;
|
||
private string __endSymbol;
|
||
private List<string> constantWords = new List<string>();
|
||
private List<string> values = new List<string>();
|
||
|
||
public ListBoxMany()
|
||
{
|
||
InitializeComponent();
|
||
}
|
||
|
||
//Устанавливает шаблонную строку и символы начала и конца переменной.
|
||
public void SetTemplateString(string templateString, string _startSymbol, string _endSymbol)
|
||
{
|
||
if (string.IsNullOrEmpty(templateString) || string.IsNullOrEmpty(_startSymbol) || string.IsNullOrEmpty(_endSymbol))
|
||
{
|
||
throw new ArgumentNullException("Введены не все значения");
|
||
}
|
||
|
||
_templateString = templateString;
|
||
__startSymbol = _startSymbol;
|
||
__endSymbol = _endSymbol;
|
||
}
|
||
|
||
//Свойство для получения или установки индекса выбранной строки в ListBox.
|
||
//Если текущий индекс не равен 0, то устанавливается новый индекс.
|
||
public int SelectedIndex
|
||
{
|
||
get { return listBox.SelectedIndex; }
|
||
set
|
||
{
|
||
if (listBox.SelectedIndex != 0)
|
||
{
|
||
listBox.SelectedIndex = value;
|
||
}
|
||
}
|
||
}
|
||
|
||
//параметризованный метод для получения объекта из выбранной строки
|
||
//T - класс, у которого есть пустой конструктор для возмож-ти создания экземпляра без параметров
|
||
public T GetObjectFromLine<T>() where T : class, new()
|
||
{
|
||
string SelectedLine = "";
|
||
|
||
if (listBox.SelectedIndex != -1)
|
||
{
|
||
SelectedLine = listBox.SelectedItem.ToString();
|
||
}
|
||
|
||
//слова из шаблонной строки
|
||
string[] wordsInTemplate = _templateString.Split(' ');
|
||
|
||
//постоянные слова
|
||
List<string> constantWords = new List<string>();
|
||
|
||
foreach (string word in wordsInTemplate)
|
||
{
|
||
if (word.StartsWith(__startSymbol))
|
||
{
|
||
continue;
|
||
}
|
||
constantWords.Add(word);
|
||
}
|
||
|
||
|
||
List<int> startsOfConstant = new List<int>();
|
||
|
||
string curString = SelectedLine;
|
||
|
||
int curIndex = 0;
|
||
foreach (string constantWord in constantWords)
|
||
{
|
||
//Нахождение const слова целиком с текущего индекса curIndex (в подстроке, начин. с curIndex)
|
||
Match match = Regex.Match(curString.Substring(curIndex), $@"\b{constantWord}\b");
|
||
int indexOfConstant = match.Index + curIndex;
|
||
startsOfConstant.Add(indexOfConstant);
|
||
curIndex = indexOfConstant + constantWord.Length;
|
||
}
|
||
|
||
//Слова, являющиеся значениями полей
|
||
List<string> values = new List<string>();
|
||
curIndex = 0;
|
||
int j = 0;
|
||
while (curIndex < SelectedLine.Length && j < constantWords.Count)
|
||
{
|
||
if (curIndex < startsOfConstant[j])
|
||
{
|
||
string value = SelectedLine.Substring(curIndex, startsOfConstant[j] - curIndex);
|
||
//если строка не пустая (не null и не одни пробелы)
|
||
if (!string.IsNullOrWhiteSpace(value))
|
||
{
|
||
//добавить её и убрать лишние пробелы перед значением и после (могут быть, могут не быть)
|
||
values.Add(value.TrimStart().TrimEnd());
|
||
}
|
||
}
|
||
curIndex = startsOfConstant[j] + constantWords[j].Length;
|
||
j++;
|
||
}
|
||
//Если текущий индекс не последний, а все постоянные слова закончились, значит до конца строки - значение
|
||
if (curIndex < SelectedLine.Length)
|
||
{
|
||
values.Add(SelectedLine.Substring(curIndex).TrimStart().TrimEnd());
|
||
}
|
||
List<string> propertyNames = new List<string>();
|
||
foreach (string word in _templateString.Split(" "))
|
||
{
|
||
if (word.Contains(__startSymbol))
|
||
{
|
||
propertyNames.Add(Regex.Replace(word.Replace(__startSymbol, "").Replace(__endSymbol, ""), @"[^\w\s]", ""));
|
||
}
|
||
}
|
||
//Получение свойств объекта и присваивание ему полученных раньше значений
|
||
T curObject = new T();
|
||
Type curType = curObject.GetType();
|
||
char[] punctuations = { '.', ',', '?', '!', ';', ':', '-', '\'', '\"' };
|
||
for (int i = 0; i < propertyNames.Count; i++)
|
||
{
|
||
PropertyInfo propertyInfo = curType.GetProperty(propertyNames[i]);
|
||
string curVal = values[i];
|
||
//если был вплотную знак препинания (в конце значения) - убрать (чтобы не было исключения)
|
||
if (punctuations.Contains(curVal[curVal.Length - 1]))
|
||
{
|
||
curVal = curVal.Remove(curVal.Length - 1);
|
||
}
|
||
|
||
var convertedValue = Convert.ChangeType(curVal, propertyInfo.PropertyType);
|
||
propertyInfo.SetValue(curObject, convertedValue);
|
||
}
|
||
|
||
return curObject;
|
||
}
|
||
|
||
//Заполняет строку в ListBox на основе значения свойства объекта dataObject.
|
||
//Если строка с указанным индексом отсутствует, она добавляется на основе шаблонной строки.
|
||
public void FillProperty<T>(T dataObject, int rowIndex, string propertyName)
|
||
{
|
||
while (listBox.Items.Count <= rowIndex)
|
||
{
|
||
listBox.Items.Add(_templateString);
|
||
}
|
||
|
||
string row = listBox.Items[rowIndex].ToString();
|
||
PropertyInfo propertyInfo = dataObject.GetType().GetProperty(propertyName);
|
||
|
||
if (propertyInfo != null)
|
||
{
|
||
object propertyValue = propertyInfo.GetValue(dataObject);
|
||
row = row.Replace($"{__startSymbol}{propertyName}{__endSymbol}", propertyValue.ToString());
|
||
listBox.Items[rowIndex] = row;
|
||
}
|
||
}
|
||
}
|
||
} |