سؤال

انا لدي ItemsControl تحتوي على قائمة بالبيانات التي أود أن أقدمها VirtualizingStackPanel.IsVirtualizing="True" لا يبدو أنه يعمل مع ItemsControl.

هل هذا هو الحال حقًا أم أن هناك طريقة أخرى للقيام بذلك لست على علم به؟

للاختبار ، كنت أستخدم الكتلة التالية من الكود:

<ItemsControl ItemsSource="{Binding Path=AccountViews.Tables[0]}"
              VirtualizingStackPanel.IsVirtualizing="True">
<ItemsControl.ItemTemplate>
    <DataTemplate>
        <TextBlock Initialized="TextBlock_Initialized"  
                   Margin="5,50,5,50" Text="{Binding Path=Name}" />
    </DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

إذا قمت بتغيير ItemsControl إلى ListBox, ، أستطيع أن أرى أن Initialized يعمل الحدث فقط على عدد قليل من الأوقات (الهوامش الضخمة هي فقط ، لذلك لا بد لي من الالتحاق ببعض السجلات) ، ولكن ك ItemsControl يتم تهيئة كل عنصر.

لقد حاولت ضبط ItemsControlPanelTemplate إلى VirtualizingStackPanel لكن هذا لا يبدو أنه يساعد.

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

المحلول

هناك في الواقع أكثر بكثير من مجرد صنع ItemsPanelTemplate استعمال VirtualizingStackPanel. الافتراضي ControlTemplate إلى عن على ItemsControl ليس لديه ملف ScrollViewer, ، وهو مفتاح المحاكاة الافتراضية. إضافة إلى قالب التحكم الافتراضي ل ItemsControl (باستخدام قالب التحكم لـ ListBox كقالب) يعطينا ما يلي:

<ItemsControl
    VirtualizingStackPanel.IsVirtualizing="True"
    ScrollViewer.CanContentScroll="True"
    ItemsSource="{Binding Path=AccountViews.Tables[0]}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBlock
                Initialized="TextBlock_Initialized"
                Text="{Binding Path=Name}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.Template>
        <ControlTemplate>
        <Border
            BorderThickness="{TemplateBinding Border.BorderThickness}"
            Padding="{TemplateBinding Control.Padding}"
            BorderBrush="{TemplateBinding Border.BorderBrush}"
            Background="{TemplateBinding Panel.Background}"
            SnapsToDevicePixels="True">
                <ScrollViewer
                    Padding="{TemplateBinding Control.Padding}"
                    Focusable="False">
                    <ItemsPresenter
                        SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
                </ScrollViewer>
            </Border>
            </ControlTemplate>
    </ItemsControl.Template>
</ItemsControl>

(راجع للشغل ، أداة رائعة للنظر في قوالب التحكم الافتراضية أرني القالب)

أشياء يجب ملاحظتها:

عليك تعيين ScrollViewer.CanContentScroll="True", ، نرى هنا لماذا.

لاحظ أيضًا أنني وضعت VirtualizingStackPanel.VirtualizationMode="Recycling". هذا سوف يقلل من أعداد الأوقات TextBlock_Initialized يتم استدعاؤه إلى العديد من أنواع النصوص المرئية على الشاشة. يمكنك قراءة المزيد على واجهة المستخدم الافتراضية هنا.

تحرير: نسيت أن تذكر ما هو واضح: كحل بديل ، يمكنك فقط استبدال ItemsControl مع ListBox :) أيضا ، تحقق من هذا تحسين الأداء على صفحة MSDN ولاحظ ذلك ItemsControl ليس في جدول "عناصر التحكم التي تنفذ ميزات الأداء" ، وهذا هو السبب في أننا نحتاج إلى تحرير قالب التحكم.

نصائح أخرى

بناءً على إجابة Davidn ، إليك نمط يمكنك استخدامه على العناصر الشهرية لإظهاره:

<!--Virtualised ItemsControl-->
<Style x:Key="ItemsControlVirtualizedStyle" TargetType="ItemsControl">
    <Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True"/>
    <Setter Property="ScrollViewer.CanContentScroll" Value="True"/>
    <Setter Property="ItemsPanel">
        <Setter.Value>
            <ItemsPanelTemplate>
                <VirtualizingStackPanel />
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ItemsControl">
                <Border
                    BorderThickness="{TemplateBinding Border.BorderThickness}"
                    Padding="{TemplateBinding Control.Padding}"
                    BorderBrush="{TemplateBinding Border.BorderBrush}"
                    Background="{TemplateBinding Panel.Background}"
                    SnapsToDevicePixels="True"
                >
                    <ScrollViewer Padding="{TemplateBinding Control.Padding}" Focusable="False">
                        <ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
                    </ScrollViewer>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

لا أحب الاقتراح لاستخدام صندوق القائمة لأنها تسمح باختيار الصفوف التي لا تريدها بالضرورة.

إنه مجرد الافتراضي ItemsPanel ليس أ VirtualizingStackPanel. تحتاج إلى تغييره:

<ItemsControl>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top