רענון הרשימה של ה-combobox ב-wpf בכל פתיחה.
-
אני מפתח תוסף חיפוש Regex עבור Word, שבו אני רוצה לאפשר למשתמש חיפוש מתקדם לפי צבעים במסמך.
מכיוון שאין אפשרות מובנית בוורד לשלוף את כל הצבעים במסמך (והרשימה המובנית של wdcolor ממש לא מכסה את כל הצבעים שיש.), אני שולף אותם ישירות מתוך ה-XML של המסמך באמצעות הקוד הבא:
public HashSet<string> ExtractColorsFromXml() { string xml = ActiveDocument.Content.WordOpenXML; HashSet<string> colors = new HashSet<string>(); // Regex to match color values in w:color attributes (e.g., <w:color w:val="C45911"/>) Regex colorRegex = new Regex(@"w:color\s+w:val=""([A-z0-9]+)""", RegexOptions.IgnoreCase); foreach (Match match in colorRegex.Matches(xml)) { colors.Add("#" + match.Groups[1].Value); } return colors; }
כדי שהמשתמש יקבל תמיד את רשימת הצבעים העדכנית (למקרה שהצבעים במסמך השתנו), אני רוצה לוודא שהקומבו בוקס מתעדכן בכל פעם שהוא נפתח.
ניסיתי לעדכן את הנתונים כאשר הרשימה נפתחת כך:
private async void ColorDropDownOpened(object sender, EventArgs e) { if (sender is ComboBox comboBox) comboBox.ItemsSource = new ColorsModel().Colors; }
יש משהו שנתקע אם פותחים את הרשימה יותר מפעם אחת ברצף - אא"כ מחכים קצת.
אבל יש תקיעות אם פותחים את הרשימה כמה פעמים ברצף – אלא אם מחכים מעט.
שאלתי היא:
מהי הדרך האופטימלית לגרום לרשימה להתעדכן בכל פעם שהיא נפתחת, מבלי לגרום לתקיעות?
האם יש דרך לעשות זאת ישר דרך ה-viewmodel? והאם זה יעזור לתקיעות הנ"ל?נ.ב. כמו"כ אשמח לדעת אם רגקס זה הדרך האופטלית לשלוף את הצבעים או שיש דרך מובנית יותר טובה ויותר מהירה להתעסק עם ה-xml.
-
@pcinfogmach לכאורה התקיעה מתרחשת בזמן שאתה מאחזר את הצבעים מה xml, מה שעולה לי בראש זה:
א. להריץ את פעולות ה Regex ב - Thread נפרד (עם Task.Run), בתוספת מחוון קטן ב - UI שהתוכנה כעת חושבת ויש לחכות כמה שניות.
ב. לעשות אופטימיזציה לפעולה עצמה, לדוגמא שימוש בניתוח xml ולא regex (ב - #C עם LINQ זה די טריוויאלי). עוד אפשרות שעולה לי בראש, זה לעקוב ב - Thread נפרד אחרי השינויים של הקובץ (אם יש אירוע שכזה) ובכל פעם שהקובץ משנה לעדכן את רשימת הצבעים, עוד לפני שהמשתמש פותח את הקומבו בוקס. -
אני חושב שאתה צריך לעקוב אחרי שינויים במסמך על ידי אירוע Change של המסמך/Application.
אני לא בטוח ולא יכול לבדוק, אבל סביר שיש כזה אירוע.
לגבי קריאת הערכים כפי שניחשת וכפי שקומפיונט מציע אפשר עם ניתוח XML:var ns = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"; var xml = XDocument.Parse(ActiveDocument.Content.WordOpenXML); var colors = xml.Descendants(XName.Get("color", ns)).Select(x => x.Attribute(XName.Get("val", ns)).Value).Distinct();
אבל לדעתי זה עדיין ייקח זמן כי המאפיין ActiveDocument.Content.WordOpenXML כנראה הוא מפעיל פעולות יקרות ולכן בשום מצב לא מתאים לעשות זאת בעת פתיחת הקומבו.
-
זה לא יכביד על התוכנה לעקוב כל הזמן אחרי שינויים הרי כל פיפס במסמך נחשב שינוי?
-
אולי כדאי להציג את הרשימה בתוך חלונית דיאולוג וחסל?
או שזה יפריע לנוחות של המשתמש? -
@pcinfogmach אפשר גם לעדכן רק על פי בקשת המשתמש, כלומר שאם הוא יפתח את רשימת הצבעים ויראה שאין את הצבע שהוא מחפש הוא ילחץ על כפתור ("רענן צבעים" לדוגמא) שיחלץ את הצבעים מחדש.
אפשרות נוספת:
כשהמשתמש פותח את הקומבו, להציג לו את הנתונים ששמורים במטמון מהפעם הקודמת, ובמקביל ב - Thread נפרד לחשב מחדש את הערכים, וכשהם מוכנים לשמור אותם למטמון ולעדכן את הקומבו הפתוח (אם הוא עדין פתוח). -
@קומפיונט כתב ברענון הרשימה של ה-combobox ב-wpf בכל פתיחה.:
ובמקביל ב - Thread נפרד לחשב מחדש את הערכים
הפעולה
string xml = ActiveDocument.Content.WordOpenXML;
רצה על ה-thread העיקרי
כמדומני שקראתי בעבר שוורד לא באמת בנוי בצורה שתומכת threading (רק משהו חיצוני לוורד אפשר אבל לא פונקציות של וורד עצמו). -
@pcinfogmach כתב ברענון הרשימה של ה-combobox ב-wpf בכל פתיחה.:
רצה על ה-thread העיקרי
אם אתה מריץ את זה בצורה הבאה, זה רץ על thread נפרד:
var xml = await Task.Run(() => ActiveDocument.Content.WordOpenXML);
כמדומני שקראתי בעבר שוורד לא באמת בנוי בצורה שתומכת threading
יתכן שהכוונה שהוא לא בטוח עם ריבוי threadים, אבל בהחלט אפשרי.