Когда я выполняю поиск символов в DataGridView, я хочу, чтобы были выбраны только искомые определенные символы (я выделяю их красным полем), не выбирая все символы в ячейке. Как мне это сделать?
Я написал код, и результат выглядит так:
Ожидаемый результат:
Я хочу, чтобы был выбран только искомый конкретный символ (я даю ему красную рамку), не выбирая все символы в ячейке
private void AddCustomer_DataGridView_CellFormatting(object? sender, DataGridViewCellFormattingEventArgs e)
{
try
{
if (e.RowIndex >= 0 && e.ColumnIndex >= 0)
{
if (!String.IsNullOrEmpty(AddCustomer_SearchTextBox.Text) && e.Value != null)
{
string strValue = (String)e.Value;
if (strValue.Contains(AddCustomer_SearchTextBox.Text))
{
DataGridViewCellStyle? cellStyle = e.CellStyle;
if (cellStyle != null)
{
// Problem ini here, how to select only specific characters in a cell (not all characters)
cellStyle.BackColor = ColorTranslator.FromHtml("#0078D7");
cellStyle.ForeColor = ColorTranslator.FromHtml("#FFFFFF");
}
}
}
}
}
catch (Exception ex)
{
ExLogger.LogException(ex, "");
MessageBox.Show(ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
// Работает нормально
public List<Customer>? SearchCustomers(int count, int minOffset, int maxOffset, string keyword, string sortExpression = "ASC")
{
if (count <= 0)
{
return new List<Customer>();
}
int limit = 1 + (maxOffset - minOffset);
if (limit < 0)
{
limit = 0;
}
int offset = minOffset - 1; // start
if (offset < 0)
{
offset = 0;
}
if (offset >= count)
{
offset = count - 1;
}
string sql = @"SELECT customer.ID, customer.created, customer.name, customer.place_of_birth, customer.date_of_birth, customer.gender_id, customer.address, customer.neighbourhood_hamlet, customer.urban_village, customer.subdistrict, customer.religion_id, customer.marital_status_id, customer.profession, customer.citizenship_id, customer.email, customer.phone_number, customer.send_me
FROM customer
INNER JOIN gender ON gender_id = gender.ID
INNER JOIN religion ON religion_id = religion.ID
INNER JOIN marital_status ON marital_status_id = marital_status.ID
INNER JOIN citizenship ON citizenship_id = citizenship.ID
WHERE customer.ID LIKE @ID OR
customer.created LIKE @created OR
customer.name LIKE @name OR
customer.place_of_birth LIKE @place_of_birth OR
customer.date_of_birth LIKE @date_of_birth OR
gender.gender_name LIKE @gender_id OR
customer.address LIKE @address OR
customer.neighbourhood_hamlet LIKE @neighbourhood_hamlet OR
customer.urban_village LIKE @urban_village OR
customer.subdistrict LIKE @subdistrict OR
religion.religion_name LIKE @religion_id OR
marital_status.marital_name LIKE @marital_status_id OR
customer.profession LIKE @profession OR
citizenship.citizenship_name LIKE @citizenship_id OR
customer.email LIKE @email OR
customer.phone_number LIKE @phone_number OR
customer.send_me LIKE @send_me
ORDER BY STR_TO_DATE(customer.created, '%d/%m/%Y %H:%i:%s') " + sortExpression + " LIMIT " + limit + " OFFSET " + offset;
object[] parms = { "@ID", '%'+ keyword + '%',
"@created", '%'+ keyword + '%',
"@name", '%'+ keyword + '%',
"@place_of_birth", '%'+ keyword + '%',
"@date_of_birth", '%'+ keyword + '%',
"@gender_id", '%'+ keyword + '%',
"@address", '%'+ keyword + '%',
"@neighbourhood_hamlet", '%'+ keyword + '%',
"@urban_village", '%'+ keyword + '%',
"@subdistrict", '%'+ keyword + '%',
"@religion_id", '%'+ keyword + '%',
"@marital_status_id", '%'+ keyword + '%',
"@profession", '%'+ keyword + '%',
"@citizenship_id", '%'+ keyword + '%',
"@email", '%'+ keyword + '%',
"@phone_number", '%'+ keyword + '%',
"@send_me", '%'+ keyword + '%'
};
return db.Read(sql, Make, parms).ToList();
}





Вы можете обработать событие CellPainting, чтобы выделить фрагменты текста внутри ячеек DataGridView.
Метод StringFormat.SetMeasurableCharacterRanges() можно использовать для создания элементов CharacterRange , которые затем передаются в Graphics.MeasureCharacterRanges() для создания регионов, описывающих границы разделов текста в этих диапазонах.
Некоторые вещи, которые следует иметь в виду:
e.PaintBackground() и e.PaintContent(), чтобы сбросить рендеринг ячеек, когда их нужно обновить, иначе вы в конечном итоге будете рисовать одну и ту же графику несколько раз на одной и той же графической поверхности.e.Handled = true, когда вы рисуете свой собственный графический контент, иначе он не будет отображаться.[StringFormat].LineAlignment = StringAlignment.Center;RectangleF с помощью [Region].GetBounds([Graphics]). Используйте Rectangle.Round(), чтобы создать Rectanglee.CellBounds для определения границ текста, который вы отправляете методам, используемым как для измерения текста, так и для рендеринга графики; если вы обнаружите, что корректируете эти границы с помощью магических чисел, в процедуре что-то не так. Если вам нужно переместить регион, используйте [Region].Translate(); чтобы переместить прямоугольник, используйте [Rectangle].Offset() или [Rectangle].Inflate()Brushes, Pens и SystemBrushes. Явное удаление этих объектов очень важно, они содержат неуправляемые ресурсы. ГК вам не поможетprivate void someDataGridView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.ColumnIndex < 0 || e.RowIndex < 0) return;
e.PaintBackground(e.ClipBounds, true);
e.PaintContent(e.ClipBounds);
var cellValue = e.FormattedValue?.ToString();
if (string.IsNullOrEmpty(searchString) || string.IsNullOrEmpty(cellValue)) return;
var positions = Regex.Matches(cellValue, searchString);
if (positions.Count == 0) return;
using (var format = new StringFormat(StringFormatFlags.FitBlackBox)) {
// The Cell's vertical alignment is usually centered. Adjust as required
format.LineAlignment = StringAlignment.Center;
// Generates ranges for all matching strings found
format.SetMeasurableCharacterRanges(positions.OfType<Match>()
.Select(m => new CharacterRange(m.Index, m.Length)).ToArray());
// Generate Regions that contain the search text
var regions = e.Graphics.MeasureCharacterRanges(cellValue, e.CellStyle.Font, e.CellBounds, format);
using (var brush = new SolidBrush(Color.FromArgb(80, Color.Fuchsia))) {
foreach (var region in regions) {
e.Graphics.FillRegion(brush, region);
// And / or draw a rectangle around the claculated box
e.Graphics.DrawRectangle(Pens.Red, Rectangle.Round(region.GetBounds(e.Graphics)));
}
}
}
e.Handled = true;
}
Вы можете подписаться на событие KeyDown TextBox для обработки ключа Enter и аннулирования вашего DataGridView при изменении строки поиска:
private string searchString = "";
private void searchTextBox_KeyDown(object sender, KeyEventArgs e) {
if (e.KeyCode == Keys.Enter) {
e.SuppressKeyPress = true;
searchString = (sender as Control).Text;
someDataGridView.Invalidate();
}
}
Вот как это работает:
Без проблем. Как примечание, вам нужно немного поработать над этим, чтобы сделать его настолько стабильным и динамичным, насколько это необходимо. Но это достойная отправная точка
@ Джими Спасибо, брат, за объяснение. Теперь я это понимаю.