Devexpress
Winform
C#
.[DEVEXPRESS] Tìm kiếm không dấu tô màu highlight có dấu trên C# Winform
Ở hình ảnh trên, các bạn thấy mình gõ vào từ khóa:
cam thuy quang
=> kết quả nó tự hiểu và tìm kiếm
Cam Thủy, Quảng Bình...
Video demo ứng dụng:
FULL SOURCE CODE CSHARP:
using DevExpress.XtraEditors.Controls; using Newtonsoft.Json; using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; using System.Windows.Forms; using System.Text.RegularExpressions; using System.Diagnostics; using System.Globalization; using DevExpress.Utils.Paint; using DevExpress.XtraGrid.Views.Base; using DevExpress.Utils.Html.Internal; using DevExpress.XtraPrinting.Native; using DevExpress.XtraPrinting; using DevExpress.XtraEditors; using static System.Windows.Forms.VisualStyles.VisualStyleElement; namespace SearchHighLightNoneVietnamese { public partial class Form1 : DevExpress.XtraEditors.XtraForm { private List<DVHC> listDVHC = new List<DVHC>(); public Color foreColorHighLight = Color.White; public Color backgroundColorHighLight = Color.YellowGreen; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { colorBackground.Color = backgroundColorHighLight; colorForeground.Color = foreColorHighLight; } protected override void OnShown(EventArgs e) { base.OnShown(e); var jsonRawData = File.ReadAllText("data.json"); listDVHC = JsonConvert.DeserializeObject<List<DVHC>>(jsonRawData); cb_diadiem.Properties.DataSource = listDVHC; cb_diadiem.AutoSuggest += repositoryItemGridLookUpEdit1_AutoSuggest; gridLookUpEdit1View.CustomDrawCell += cbDiadiem_CustomDrawCell; cb_diadiem.Properties.ValueMember = "maxa"; cb_diadiem.Properties.DisplayMember = "diadiem"; cb_diadiem.Properties.PopupFormSize = new System.Drawing.Size(cb_diadiem.Width, 300); cb_diadiem.BeforePopup += Cb_diadiem_BeforePopup; cb_diadiem.Popup += Cb_diadiem_Popup; LoadTinhThanh(); LoadQuanHuyen(); LoadPhuongXa(); this.KeyPreview = true; this.KeyDown += Form1_KeyDown; } private void Cb_diadiem_Popup(object sender, EventArgs e) { gridLookUpEdit1View.CustomDrawCell += cbDiadiem_CustomDrawCell; } private void Cb_diadiem_BeforePopup(object sender, EventArgs e) { gridLookUpEdit1View.CustomDrawCell -= cbDiadiem_CustomDrawCell; } private void Form1_KeyDown(object sender, KeyEventArgs e) { if (e.Control && e.KeyCode == Keys.K) { cb_diadiem.Focus(); cb_diadiem.SelectAll(); } } public void LoadTinhThanh() { var dataTinhThanh = listDVHC.Select(x => new { matinh = x.matinh, tentinh = x.tentinh }).Distinct().ToList(); cb_tinhthanh.Properties.DataSource = dataTinhThanh; cb_tinhthanh.Properties.ValueMember = "matinh"; cb_tinhthanh.Properties.DisplayMember = "tentinh"; } public void LoadQuanHuyen() { var dataQuanHuyen = listDVHC.Select(x => new { mahuyen = x.mahuyen, tenhuyen = x.tenhuyen }).Distinct().ToList(); cb_quanhuyen.Properties.DataSource = dataQuanHuyen; cb_quanhuyen.Properties.ValueMember = "mahuyen"; cb_quanhuyen.Properties.DisplayMember = "tenhuyen"; } public void LoadPhuongXa() { var dataPhuongXa = listDVHC.Select(x => new { maxa = x.maxa, tenxa = x.tenxa }).Distinct().ToList(); cb_phuongxa.Properties.DataSource = dataPhuongXa; cb_phuongxa.Properties.ValueMember = "maxa"; cb_phuongxa.Properties.DisplayMember = "tenxa"; } private void cbDiadiem_CustomDrawCell(object sender, RowCellCustomDrawEventArgs e) { XPaint paint = new XPaint(); MultiColorDrawStringParams drawParams = new MultiColorDrawStringParams(e.Appearance); var searchText = cb_diadiem.Text; if (e.DisplayText.Length < searchText.Length) return; drawParams.Bounds = e.Bounds; drawParams.Text = e.DisplayText; string tmpStr = e.DisplayText; var searchIndexesListOrigin = getListIndexMatch(e.DisplayText, searchText); if (searchIndexesListOrigin.Count == 0) return; var searchIndexesList = searchIndexesListOrigin.OrderBy(x => x.Item2).ToList(); if (searchIndexesList.Count() > 0) { drawParams.Ranges = new CharacterRangeWithFormat[searchIndexesList.Count() * 2 + 1]; int currentStrIndex = 0; int i = 0; while (i < searchIndexesList.Count()) { drawParams.Ranges[i * 2] = new CharacterRangeWithFormat(currentStrIndex, searchIndexesList[i].Item2 - currentStrIndex, e.Appearance.ForeColor, e.Appearance.BackColor); drawParams.Ranges[i * 2 + 1] = new CharacterRangeWithFormat(searchIndexesList[i].Item2, searchIndexesList[i].Item3 - searchIndexesList[i].Item2, foreColorHighLight, backgroundColorHighLight); currentStrIndex = searchIndexesList[i].Item3; i++; } drawParams.Ranges[i * 2] = new CharacterRangeWithFormat(currentStrIndex, e.DisplayText.Length - currentStrIndex, e.Appearance.ForeColor, e.Appearance.BackColor); drawParams.Ranges = drawParams.Ranges.Where(val => val.Length != 0).ToArray(); } paint.MultiColorDrawString(new DevExpress.Utils.Drawing.GraphicsCache(e.Graphics), drawParams); e.Handled = true; } public int AccentInsensitiveIndexOf(string source, string subStr) { // return CultureInfo.InvariantCulture.CompareInfo.IndexOf(source, subStr, CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace); var keyword = BoDauTiengViet(subStr); //Regex.Match(source, $@"\W{keyword}\W").Index; var match = Regex.Match(source, $@"\b{keyword}\b"); int index = match.Success ? match.Index : -1; return index; } public List<(string, int, int)> getListIndexMatch(string source, string subStr) { var listdata = new List<(string, int, int)>(); string[] stringSeparators = new string[] { " " }; var sourceArr = source.Split(stringSeparators, StringSplitOptions.RemoveEmptyEntries); var arrKeywork = subStr.Split(stringSeparators, StringSplitOptions.RemoveEmptyEntries); foreach (string keyword in arrKeywork) { var start = AccentInsensitiveIndexOf(BoDauTiengViet( source), keyword); var end = start + keyword.Length; var item = (keyword, start, end); if(start >= 0) { bool isStartBoundary = (start == 0) || char.IsWhiteSpace(source[start - 1]); bool isEndBoundary = (end == source.Length) || char.IsWhiteSpace(source[end]); // var stringMatch = source.Substring(start, keyword.Length); // var isWordMatch = keyword == BoDauTiengViet(stringMatch); // if (isWordMatch) // if (isStartBoundary || isEndBoundary) { listdata.Add(item); //} } } return listdata; } public Task<ICollection> QueryAsync(string keywords, CancellationToken cancellation) { return Task.Run(() => { if (!string.IsNullOrEmpty(keywords)) { return FilterDVHCByKeyWords(listDVHC, keywords) as ICollection; } else { return listDVHC as ICollection; } }); } private void repositoryItemGridLookUpEdit1_AutoSuggest(object sender, LookUpEditAutoSuggestEventArgs e) { e.SetMinimumAnimationDuration(TimeSpan.FromMilliseconds(100)); e.QuerySuggestions = QueryAsync(e.Text, e.CancellationToken); } public List<DVHC> FilterDVHCByKeyWords(List<DVHC> data, string keyworks) { string[] pattern_split = new string[] { " " }; string[] arr_keywords = keyworks.Split(pattern_split, StringSplitOptions.RemoveEmptyEntries); var cleanedKeywords = arr_keywords.Select(k => BoDauTiengViet(k)); var regexPattern = string.Join(".*", cleanedKeywords.Select(Regex.Escape)); var regex = new Regex(regexPattern, RegexOptions.IgnoreCase); return data.Where(item => regex.IsMatch(BoDauTiengViet(item.diadiem))).ToList(); } public string BoDauTiengViet(string str) { str = str.ToLower().Trim(); str = Regex.Replace(str, "[àáạảãâầấậẩẫăằắặẳẵ]", "a"); str = Regex.Replace(str, "[èéẹẻẽêềếệểễ]", "e"); str = Regex.Replace(str, "[ìíịỉĩ]", "i"); str = Regex.Replace(str, "[òóọỏõôồốộổỗơờớợởỡ]", "o"); str = Regex.Replace(str, "[ùúụủũưừứựửữ]", "u"); str = Regex.Replace(str, "[ỳýỵỷỹ]", "y"); str = Regex.Replace(str, "đ", "d"); // str = Regex.Replace(str, " ", "-"); str = str.Replace(",", " "); str = str.Replace(".", " "); return str; } private void colorForeground_EditValueChanged(object sender, EventArgs e) { foreColorHighLight = colorForeground.Color; } private void colorBackground_EditValueChanged(object sender, EventArgs e) { backgroundColorHighLight = colorBackground.Color; } private void cb_diadiem_EditValueChanged(object sender, EventArgs e) { if (cb_diadiem.EditValue != null) { var selectedRow = cb_diadiem.GetSelectedDataRow() as DVHC; cb_tinhthanh.EditValue = selectedRow.matinh; cb_quanhuyen.EditValue = selectedRow.mahuyen; cb_phuongxa.EditValue = selectedRow.maxa; } } } public class DVHC { public string diadiem { get; set; } public string maxa { get; set; } public string tenxa { get; set; } public string mahuyen { get; set; } public string tenhuyen { get; set; } public string matinh { get; set; } public string tentinh { get; set; } } }
Chúc mọi người thành công với thủ thuật trên.