سؤال

انا لدي ObservableCollection من المعطلين الذين يجلسون في WPF DataGrid. وبعد ال DataGrid لديه ثلاثة أعمدة:

  • عمود الموقف؛ يتم تقديم هذا في وقت التشغيل بواسطة UserControl يعرض موضع الصف في DataGrid الخاص بي
  • اسم العمود؛ يتم تقديم هذا في وقت التشغيل بواسطة USERCONTROL يعرض اسم العمود (نعم، أحتاج إلى UserControl لهذا بناء على كيفية عرض الاسم، ولكن هذا جانبا)
  • عمود البيانات يتم تقديم هذا في وقت التشغيل بواسطة UserControl آخر.

يتم تعريف أعمدة بلدي مثل هذا:

        <toolkit:DataGrid.Columns>
            <toolkit:DataGridTemplateColumn Header="" MinWidth="35" MaxWidth="35" SortMemberPath="Position.PositionIndex" CanUserSort="True">
                <toolkit:DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ContentPresenter Content="{Binding Path=Position}"/>
                    </DataTemplate>
                </toolkit:DataGridTemplateColumn.CellTemplate>
            </toolkit:DataGridTemplateColumn>
            <toolkit:DataGridTemplateColumn Header="Name" MinWidth="150" Width="150" SortMemberPath="Name" CanUserSort="True">
                <toolkit:DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ContentPresenter Content="{Binding Path=Name}"/>
                    </DataTemplate>
                </toolkit:DataGridTemplateColumn.CellTemplate>
            </toolkit:DataGridTemplateColumn>
            <toolkit:DataGridTemplateColumn Header="Data" Width="Auto" CanUserSort="False">
                <toolkit:DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ContentPresenter Content="{Binding Path=Data}"/>
                    </DataTemplate>
                </toolkit:DataGridTemplateColumn.CellTemplate>
            </toolkit:DataGridTemplateColumn>
        </toolkit:DataGrid.Columns>

لذلك، لأن أعمدة الصف وأعمدة الاسم هي UserControls، WPF DataGrid لا يمكن أن فرز فقط عليها. لذلك لتسهيل الفرز، عند النقر فوق رأس العمود، أفعل بعض ListCollectionView.CustomSort سحر.

هنا هو ما تبدو فيه المرتفعات المخصصة لعمود الاسم:

// Customized sorter, by name, ascending.
public class AscendingNameSorter : IComparer
{
    public int Compare(object x, object y)
    {
        var lhs = (MyViewModel)x;
        var rhs = (MyViewModel)y;

        return lhs.Name.CompareTo(rhs.Name);
    }
}

// Customized sorter, by name, descending.
public class DescendingNameSorter : IComparer
{
    public int Compare(object x, object y)
    {
        var lhs = (MyViewModel)x;
        var rhs = (MyViewModel)y;

        return rhs.Name.CompareTo(lhs.Name);
    }
}

المشكلة هي أن هذا هو بطيئة بشكل لا يصدق. وبعد لا أستطيع معرفة السبب. مع 10 عناصر في DataGrid, ، تطبيقي يطحن إلى وقف لمدة 3-4 ثواني أثناء المنتجعات. اعتقدت ListCollectionView.CustomSort كان من المفترض أن تكون الطريقة الأكثر فعالية لفرز ObservableCollection... هل أنا على خطأ؟

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

المحلول

يقوم WPF بإعادة إنشاء جميع UserControls في كل مرة تغيرات الفرز، لذلك تخميني هو أن شيئا ما في بناء تلك الضوابط بطيئة. ولكن هذا هو مجرد تخمين.

يجب أن تبدأ بتضييق المشكلة. فيما يلي بعض الخطوات التي يمكنك اتخاذها:

  1. تعرف على العملية التي تستغرق 3-4 ثواني. أنت لم تذكر ما إذا كان التأخير يحدث فقط عند تعيين القيمة إلى Gustomest، أو في كل مرة يتم فيها تعيين تغييرات القائمة بعد GoardORT. هذا يحدث فرقا.

  2. حاول إضافة عمود نص منتظم وفرزه باستخدام الترتيب المدمج لمعرفة ما إذا كان سريعا أم لا. ربما كنت قد فعلت هذا بالفعل، لكنك لم تقل في سؤالك.

  3. بالنسبة لأغراض التشخيص، توقف مؤقتا عن إعداد GuideOrT و Set LetCollectionView.filter بدلا من ذلك. اضبطه على مرشح يعود دائما صحيحا. إذا كنت لا تزال تحصل على التباطؤ، ترتبط المشكلة بمحاولة ListCollectionView لإعادة تنظيم العناصر.

  4. قم بتحرير قوالبك مؤقتا واستبدل UserControls المخصص بشيء تافهة (على سبيل المثال <CheckBox/>) لمعرفة ما إذا كانت الأمور تسريع أم لا.

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

  6. إضافة رمز إلى منشئتك UserControl لكتابة DateTime.Now تم استدعاء المنشئين إلى نافذة الإخراج (أو سجل أو أي شيء). هذا سوف يعطيك فكرة كم من الوقت يستغرق كل منهما.

  7. أضف عدة مئات من العناصر إلى الملاحظ الخاص بك، قم بتشغيل تطبيقك جانب جنبا إلى جنب مع vs.net، انقر فوق الزر "فرز" الخاص بك (أو أيا كان)، ثم اضغط على الزر "كسر الكل" في vs.net وانظر إلى تتبع المكدس. ضرب متابعة وضرب الفاصل على الفور مرة أخرى، ثم انظر إلى تتبع المكدس مرة أخرى. كرر عدة مرات. هذا سوف يمنحك فكرة جيدة عن ما يستغرق كل الوقت الإضافي.

إذا كنت تشك، فإن المشكلة هي إنشاء وملزمة بطيئة UserControls، وستجد: المشكلة تحدث في كل قائمة تغييرات وأحدث أيضا عند تغيير المرشح، والأشياء تسريع عند استبدال UserControls <CheckBox/>, ، لن يتم استدعاء منشئك مرة واحدة فقط لكل عنصر، والوقت بين المكالمات سيكون باردا.

لاحظ أنني لا أقول ذلك هو البناء من UserControls التي تكون بطيئة - قد تكون أن تقوم UserControl بمثابة إنشاء العديد من الكائنات الفرعية عندما تكون مرتبطة بالبيانات، أو أنها تتضمن كائنات بطيئة أو معقدة، أو تحميل ملف، أو العديد من الأسباب المحتملة الأخرى. إن خلاصة القول هو أن إنشاء ملف بيانات حول الكائن وإضافةه إلى الشجرة المرئية يفعل شيئا بطيئا. يجب أن تمنحك آثار المكدس فكرة أن ننظر إليها.

إذا اتضح أنه شيء آخر أو لا يمكنك معرفة ذلك، ما عليك سوى تحديث سؤالك لإعطاء مزيد من المعلومات حول ما كشفت الاختبارات المذكورة أعلاه، وسنحاول مساعدتك.

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