سؤال

لدي الدرجة يسمى الكتاب ؛

class Book
{
    public string Name { get; set; }
    public string Author { get; set; }
    public int PagesCount { get; set; }
    public int Category { get; set; }
}

ListBox يعرض قائمة من الكتب ItemTemplate تم تعديلها بحيث تمثل بصريا الكتاب.النص يظهر اسم الكتاب المؤلف عدد الصفحات.الفئة ومع ذلك يمثل لون معين (على سبيل المثال ، والتاريخ هو الأزرق, الرومانسية الحمراء.... الخ) الآن النص لديه OuterGlowBitmap تأثير قيمة محول من الفئة (الباحث) إلى اللون المناسب.كل شيء لا بد في DataTemplate على ListBoxItem.من الناحية الفنية, كل شيء يعمل بشكل جيد.

ولكن المشكلة هو الأداء.يبدو أن outerGlow نقطية تأثير ثقيل على المعالج, حتى عندما يكون لدي قائمة من حوالي 500 الكتب يستغرق حوالي 500ms لإستعادة البيانات من قاعدة البيانات ولكن حوالي 10 ثوان في الواقع تحميل العناصر في مربع القائمة.وحتى عند التحميل يتم التمرير جدا laggy.لقد حاولت تعيين VirtualizingStackPanel.IsVirtualizing إلى صحيح ، ولكن دون جدوى.(أقصى عدد من الكتب التي يمكن أن تكون قاعدة البيانات في أي وقت من الأوقات حوالي 30000.)

ومع ذلك ، حتى عندما يكون هناك أكثر من 100 من العناصر في مربع القائمة العقل البشري لا يمكن معالجة ذلك بكثير بسرعة لذا لا تهدف إلى تحميل قائمة للمستخدم جميع الكتب التي يتم البحث عنها.هذا هو السبب في أنني خلقت مجمع الملاحة الدرجة BookNavigator فعلا يربط listbox إلى ObservableCollection الكائن.جميع الكتب التي يتم تحميلها في هذا BookNavigator ، ولكن فقط X منهم يتم عرضها في مربع القائمة (عن طريق إضافتها إلى observableCollection).

المشكلة مع ذلك هو أنني أريد أن عدد من عرض الكتب إلى أن تكون صغيرة بما يكفي listbox عدم عرض شريط التمرير حتى أستطيع تنفيذ أساليب التمرير (الأولى, السابق, التالي, آخر, أو ببساطة بلدي التمرير, لا يهم).

كيف يمكن حساب عدد العناصر التي يتم عرضها حتى التمرير لا تظهر ؟

اثنين من المشاكل التي يطفو على السطح:- تغيير حجم التطبيق يمكن تغيير حجم مربع القائمة - ليس كل listbox العناصر من نفس الارتفاع (اعتمادا على عدد من المؤلفين).

هل هناك أي طريقة لتحقيق ما أحاول أن أفعله ؟


تحرير (الرد على مارتن هاريس)

مشكلة مع رمز مارتن هاريس اقترح هو أن حلقة foreach يستخدم FrameworkElement ، ولكن listbox يتم تعبئة مع كائنات من نوع الكتاب الذي لا يرث من FrameworkElement ولا له أي يعني حساب الارتفاع.على ListBoxItem الجذر عنصر الشبكة ، لذا ربما كان من الممكن لإستعادة هذه الشبكة ، ولكن لا نعرف كيف نفعل ذلك ؟

هل هناك أي طريقة للحصول على الفعلية عناصر واجهة المستخدم التي تم إنشاؤها لتمثيل listbox البند ؟


تحرير

لقد وجدت هذا س/أ والتي يبدو أن ما أحتاج..ItemContainerGenerator

هل كانت مفيدة؟

المحلول 4

الحل يمكن أن ضمنا يمكن العثور عليها هنا:الحل

نصائح أخرى

بعد محاولة لمعرفة شيء مماثل ، ظننت أنني سوف تتقاسم النتيجة هنا (كما يبدو أسهل من الردود الأخرى):

بسيطة الرؤية الاختبار حصلت من هنا.

private static bool IsUserVisible(FrameworkElement element, FrameworkElement container)
{
    if (!element.IsVisible)
        return false;

    Rect bounds =
        element.TransformToAncestor(container).TransformBounds(new Rect(0.0, 0.0, element.ActualWidth, element.ActualHeight));
    var rect = new Rect(0.0, 0.0, container.ActualWidth, container.ActualHeight);
    return rect.Contains(bounds.TopLeft) || rect.Contains(bounds.BottomRight);
}

بعد ذلك يمكنك حلقة من خلال listboxitems و استخدام هذا الاختبار لتحديد مرئية.عدد من هذه القائمة سوف تعطيك عدد من العناصر المرئية في مربع القائمة.

private List<object> GetVisibleItemsFromListbox(ListBox listBox, FrameworkElement parentToTestVisibility)
{
    var items = new List<object>();

    foreach (var item in PhotosListBox.Items)
    {
        if (IsUserVisible((ListBoxItem)listBox.ItemContainerGenerator.ContainerFromItem(item), parentToTestVisibility))
        {
            items.Add(item);
        }
        else if (items.Any())
        {
            break;
        }
    }

    return items;
}

وهذا من شأنه أن تحتوي على قائمة البنود المعروضة حاليا في مربع القائمة (بما في ذلك تلك التي كانت مخبأة عن طريق التمرير أو شيئا من هذا القبيل).

يمكنك ربما يمكن أن معرفة أحجام من جميع الكتب قبل إضافتها إلى مربع القائمة (ربما عن طريق تحليل و ملء القالب XAML في التعليمات البرمجية خلف ثم يسأل الخارجي التحكم في حجمها) هذا من شأنه أن يكون هناك الكثير من العمل عن كسب.لا يمكنك ببساطة اختيار عدد من الكتب التي سوف تكون كافية لملء مربع القائمة ، ولكن ليس الكثير من بطء تقديم أسفل وتحويل شريط التمرير ؟ هذا يمكن أن يكون لا يزال يرتبط حجم مربع القائمة بحيث كما نمت أكثر البنود المضافة ، ولكن أداء تكلفة إضافة بعض البنود الإضافية يجب أن يكون أقل تكلفة من حساب جميع الأحجام مرة أخرى.

مثال سريع:دعنا نقول أن حجم كتاب مع مؤلف واحد هو 150 بكسل.هل يمكن أن تأخذ حجم مربع القائمة تقسيم 125 للحصول على تقدير تقريبي لعدد من البنود التي من شأنها أن تكون في الملعب, ولكن ليس مكلفا حساب.ما كنت ترغب في تجنب جدا قليل من البنود منذ أن ترك مساحة فارغة.


تحريرها في ضوء التعليق الخاص بك.

في هذه الحالة يمكنك إضافة عناصر إلى مربع القائمة (باستخدام الطريقة أعلاه للحصول على وثيقة تخمين) ، ثم حساب آخر تماما عنصر مرئي ثم إزالة البنود الإضافية.

هذا التمديد الطريقة سوف تحصل على آخر عنصر تماما تظهر في مربع القائمة أو لاغية إذا لم العناصر المرئية:

public static class ListBoxExtensions
{
    public static FrameworkElement GetLastItem(this ListBox listBox)
    {
        double height = listBox.ActualHeight;

        double currentHeight = 0;
        FrameworkElement previous = null;

        foreach (FrameworkElement item in listBox.Items)
        {
            currentHeight += item.ActualHeight;
            if (currentHeight > height)
            {
                return previous;
            }

            previous = item;
        }

        return previous;
    }
}

إذا كان يرصد قائمة أكبر ثم يمكنك إضافة ما يكفي من المواد إلى المجموعة التي كنت في ملء فجوة إعادة تشغيل العملية.

"كيف يمكن حساب عدد العناصر التي يتم عرضها حتى التمرير لا تظهر ؟ "

الجواب القصير:(listBox1.الطول/ listBox1.ItemHeight)

هذا يتيح لك عرض العدد/الخطوط المتاحة ، بحيث يمكنك قراءة فقط هذا العدد من خطوط ملء كل مربع القائمة.

الآن التجريبي:

        int listbox_total_visible_lines = 2;
        listBox1.Height = (listbox_total_visible_lines + 1) * listBox1.ItemHeight;
        listBox1.Items.Add("um");
        listBox1.Items.Add("dois");
        listBox1.Items.Add("tres");
        listBox1.Items.Add("quatro");
        listBox1.Items.Add("cinco");
        listBox1.SelectedIndex = listBox1.Items.Count - 1;
        this.Text = (listBox1.Height/ listBox1.ItemHeight).ToString();

هذا المثال دعونا لك اختيار عدد من العناصر التي سوف تكون مرئية ، لذلك عدد os الخطوط التي هي في الحقيقة المتاحة للعرض.لذلك يمكنك إضافة فقط "listbox_total_visible_items" العناصر listbox سوف تكون كاملة و لا تظهر أشرطة التمرير.

رمز شرح:

  1. listbox_total_visible_items يحتوي على عدد من الخطوط التي سيتم عرضها

  2. الإعداد listbox مع الحجم المناسب ، 2 خطوط فقط

3-7.إضافة بعض الخطوط

  1. انتقل إلى السطر الأخير فقط من أجل المتعة

  2. تظهر على شكل شريط النص ، وعدد من listbox خطوط على أساس listbox ارتفاع مقسوما على حجم كل عنصر.

هذا هو.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top