treenode بطيئة مع مربعات الاختيار [كمية كبيرة
سؤال
يتحقق الحدث بعد تحكم Tree View Control من جميع العقد الفرعية الموجودة أسفله ويمكّن زر التشغيل إذا تم التحقق من شيء ما.
1346 void TreeNode_AfterCheck(object sender, TreeViewEventArgs e) {
1347 if (!e.Node.Checked) return;
1348 foreach (TreeNode sub in e.Node.Nodes) {
1349 sub.Checked = e.Node.Checked;
1350 }
1351 RunButton.Enabled = IsANodeChecked();
1352 }
1429 static bool IsANodeChecked(TreeNode node) {
1430 if (node.Checked) return true;
1431 foreach (TreeNode sub in node.Nodes) {
1432 if (IsANodeChecked(sub)) {
1433 return true;
1434 }
1435 }
1436 return false;
1437 }
التحقق من عقدة الجذر عندما يكون هناك 4881 العقد الفرعية سوف تعلق واجهة المستخدم الرسومية لمدة 7 ثوانٍ تقريبًا.
أنا فقط بحاجة إلى استدعاء isanodechecked (على السطر 1351) مرة واحدة ، لكنني لا أعرف كيفية تعطيلها حتى تتم معالجة جميع العقد الشجرة.
وأنا لا أريد أن يكون لدي مؤقت في النموذج الخاص بي مخصص لمراقبة هذا.
هل يرى أي شخص حلًا بسيطًا/واضحًا؟
المحلول 3
هذه الأفكار حيث تكون مفيدة ، لكنني استخدمت شيئًا مختلفًا يعمل عن طريق إضافة متغير منطقي واحد:
bool _treeNodeFirst = false;
... وحدث قبل التحقق من تعديل اللون الخلفي مؤقتًا على عنصر التحكم ليكون بمثابة علامة للتحكم الذي بدأ سلسلة الأحداث:
1273 void TreeNode_BeforeCheck(object sender, TreeViewCancelEventArgs e) {
1274 if (!_treeNodeFirst) {
1275 _treeNodeFirst = true;
1276 e.Node.BackColor = Color.Silver;
1277 }
1278 }
1346 void TreeNode_AfterCheck(object sender, TreeViewEventArgs e) {
1347 if (e.Node.Checked) {
1348 foreach (TreeNode sub in e.Node.Nodes) {
1349 sub.Checked = e.Node.Checked;
1350 }
1351 }
1352 if (e.Node.BackColor == Color.Silver) {
1353 e.Node.BackColor = Color.Empty;
1354 RunButton.Enabled = IsANodeChecked();
1355 _treeNodeFirst = false;
1356 }
1357 }
1429 static bool IsANodeChecked(TreeNode node) {
1430 if (node.Checked) return true;
1431 foreach (TreeNode sub in node.Nodes) {
1432 if (IsANodeChecked(sub)) {
1433 return true;
1434 }
1435 }
1436 return false;
1437 }
يبدو أن هذه هي أفضل طريقة (يمكنني رؤيتها الآن) لضمان ذلك IsANodeChecked(TreeNode)
يتم تشغيله مرة واحدة فقط عند اختيار مجموعة من العقد في وقت واحد.
ومع ذلك ، أحب حقًا فكرة جيمي هوفا عن استخدام عدد. ربما سأضيف ذلك إلى الكود الخاص بي.
شكرا للجميع! ~ جو
نصائح أخرى
ضع معالج الأحداث على مربعات الاختيار التي تمكن أو تعطيل Runbutton بدلاً من وجود شيء يكرر الأمر كله لمعرفة ذلك.
أضف مربع الاختيار إلى قائمة مربعات الاختيار التي تم تحديدها عندما يتم فحصها أولاً حتى لا تقوم بتعطيل Runbutton حتى تصبح قائمة مربعات الاختيار التي تم فحصها فارغة. قم بإزالتها من القائمة عندما يتم عدم رادعها ، إلخ.
إليك نوعًا ما من كيفية كتابته ، هذا مجرد تجنيده آسف جدًا إذا فاتني شيء ما:
private int _checkedCheckboxes;
void AddCheckBox()
{
if (_checkedCheckBoxes++ == 1) RunButton.Enabled = true;
}
void RemoveCheckBox()
{
if (_checkedCheckBoxes-- == 0) RunButton.Enabled = false;
}
void TreeNode_AfterCheck(object sender, TreeViewEventArgs e)
{
if (e.Node.Checked)
{
AddCheckBox();
return;
}
RemoveCheckBox();
}
أستخدم أحيانًا أ Timer
للتعامل مع مثل هذه الحالات. أضف مؤقتًا وقم بإعداد ملف Tick
معالج الأحداث للاتصال IsANodeChecked
وتمكين/تعطيل الزر. امنحه فاصلًا قصيرًا (~ 100 مللي ثانية ربما) ، واتركه معاقًا. ثم تتصل Stop
تليها Start
على الموقت في الخاص بك AfterCheck
معالج الأحداث. سيؤدي ذلك إلى إعادة تشغيل المؤقت لكل مكالمة AfterCheck
, ، لكن ال Tick
لن يتم استدعاء معالج الأحداث إلا عند انقضاء وقت معين بعد Start
مكالمة ، مما يعني أنه لن يتم الاحتجاج به حتى بعد آخر مكالمة إلى AfterCheck
.
100 مللي ثانية جداً وقت طويل حتى يعمل الكمبيوتر ، ولكن سيبدو فوريًا للمستخدم.
يمكنك رؤية سلوك مماثل في مستكشف Windows. إذا كنت تستخدم لوحة المفاتيح للتنقل بسرعة في شجرة المجلد ، فلن يتم تحديث جزء اليد اليمنى مع محتويات المجلد إلا إذا بقيت على مجلد في الشجرة للحظة وجيزة.