Files
PIbd-32_BuslaevRoman_KOP/WinFormsControlLibrary1/TemplatedListBox.cs

170 lines
4.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
using WinFormsControlLibrary1.Exceptions;
namespace WinFormsControlLibrary1;
public partial class TemplatedListBox : UserControl
{
private readonly ListBox _lb = new() { Dock = DockStyle.Fill };
private string _template = "";
private string _open = "{";
private string _close = "}";
public event EventHandler? SelectedIndexChanged;
public TemplatedListBox()
{
InitializeComponent();
Controls.Add(_lb);
_lb.HorizontalScrollbar = true;
_lb.SelectedIndexChanged += (_, __) => SelectedIndexChanged?.Invoke(this, EventArgs.Empty);
}
public void SetTemplate(string template, string open = "{", string close = "}")
{
if (string.IsNullOrWhiteSpace(template))
throw new TemplateConfigurationException("Шаблон не должен быть пустым.");
_template = template;
_open = open;
_close = close;
if (template[0] == open[0] || template[template.Length - 1] == close[0])
throw new TemplateConfigurationException("Шаблон не должен начинаться или заканчиваться свойством.");
CheckNoDoubleProperties(template, open, close);
}
public void Clear()
{
_lb.Items.Clear();
}
public void AddItem<T>(T item)
{
if (string.IsNullOrEmpty(_template))
throw new TemplateConfigurationException("Сначала вызовите SetTemplate.");
var text = Render(item);
_lb.Items.Add(text);
}
private string Render(object obj)
{
if (string.IsNullOrEmpty(_template)) return string.Empty;
string result = _template;
var type = obj.GetType();
foreach (var p in type.GetProperties())
{
if (!p.CanRead) continue;
string name = p.Name;
string val = Convert.ToString(p.GetValue(obj)) ?? string.Empty;
result = result.Replace($"{_open}{name}{_close}", val);
}
foreach (var f in type.GetFields())
{
string name = f.Name;
string val = Convert.ToString(f.GetValue(obj)) ?? string.Empty;
result = result.Replace($"{_open}{name}{_close}", val);
}
return result;
}
public T? GetSelectedObject<T>() where T : class, new()
{
if (_lb.SelectedIndex == -1)
{
return null;
}
string row = _lb.SelectedItem!.ToString()!;
T obj = new T();
var type = typeof(T);
List<string> substrings = new List<string>();
List<string> props = ExtractPlaceholders(_template, _open, _close);
string template = _template;
substrings.AddRange(template.Split(_open + _close));
int int1 = 0; int int2 = 0;
for (int i = 0; i < props.Count; i++)
{
int1 = row.IndexOf(substrings[i]) + substrings[i].Length;
int2 = row.IndexOf(substrings[i + 1]);
if (substrings[i + 1] == "")
{
int2 = row.Length;
}
var value = row[int1..int2];
var p = type.GetProperty(props[i]);
if (p is null) continue;
p.SetValue(obj, Convert.ChangeType(value, p.PropertyType));
}
return obj;
}
private List<string> ExtractPlaceholders(string template, string open, string close)
{
var names = new List<string>();
int i = 0;
while (i < template.Length)
{
if (template[i] == open[0])
{
int j = template.IndexOf(close, i + 1, StringComparison.Ordinal);
string name = template.Substring(i + 1, j - i - 1).Trim();
names.Add(name);
i = j + 1;
}
else i++;
}
return names;
}
private static void CheckNoDoubleProperties(string template, string open, string close)
{
for (int i = 0; i < template.Length; i++)
{
if (template[i] == close[0])
{
int k = i + 1;
while (k < template.Length && char.IsWhiteSpace(template[k])) k++;
if (k < template.Length && template[k] == open[0])
throw new TemplateConfigurationException("В шаблоне не должно идти два свойства подряд без текста между ними.");
}
}
}
}