قم بإنشاء WPF ItemTemplate ديناميكيًا في وقت التشغيل

StackOverflow https://stackoverflow.com/questions/125638

  •  02-07-2019
  •  | 
  •  

سؤال

في وقت التشغيل، أرغب في إنشاء أعمدة الشبكة (أو تخطيط عرض آخر) ديناميكيًا في WPF ListView.لا أعرف عدد وأسماء الأعمدة الموجودة مسبقًا.

أريد أن أكون قادرًا على القيام بما يلي:
MyListView.ItemSource = MyDataset;
MyListView.CreateColumns();

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

المحلول

سأحاول اتباع النهج التالي:

أ) يجب أن يكون لديك عرض شبكة عرض مربع القائمة - أعتقد أنك قمت بذلك بالفعل
ب) تحديد نمط لـ GridViewColumnHeader:

        <Style TargetType="{x:Type GridViewColumnHeader}" x:Key="gridViewColumnStyle">
            <EventSetter Event="Click" Handler="OnHeaderClicked"/>
            <EventSetter Event="Loaded" Handler="OnHeaderLoaded"/>
        </Style>

في حالتي، كان لدي مجموعة كاملة من الخصائص الأخرى، ولكن في السيناريو الأساسي - ستحتاج إلى حدث Loaded.تم النقر عليه - وهذا مفيد إذا كنت تريد إضافة وظيفة الفرز والتصفية.

ج) في كود عرض القائمة الخاص بك، قم بربط القالب مع عرض الشبكة الخاص بك:

    public MyListView()
    {
        InitializeComponent();
        GridView gridViewHeader = this.listView.View as GridView;
        System.Diagnostics.Debug.Assert(gridViewHeader != null, "Expected ListView.View should be GridView");
        if (null != gridViewHeader)
        {
            gridViewHeader.ColumnHeaderContainerStyle = (Style)this.FindResource("gridViewColumnStyle");
        }
    }

د) ثم في معالج OnHeaderLoaded، يمكنك تعيين قالب مناسب بناءً على بيانات العمود

    void OnHeaderLoaded(object sender, RoutedEventArgs e)
    {
        GridViewColumnHeader header = (GridViewColumnHeader)sender;
        GridViewColumn column = header.Column;

// حدد وقم بتطبيق قالب البيانات الخاص بك هنا.

        e.Handled = true;
    }

هـ) أعتقد أنك ستحتاج أيضًا إلى الحصول على ملكية خاصية التبعية ItemsSource والتعامل مع حدث التغيير.

            ListView.ItemsSourceProperty.AddOwner(typeof(MyListView), new PropertyMetadata(OnItemsSourceChanged));

        static void OnItemsSourceChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            MyListView view = (MyListView)sender;
            //do reflection to get column names and types
            //and for each column, add it to your grid view:
            GridViewColumn column = new GridViewColumn();
            //set column properties here...
            view.Columns.Add(column);
        }

لا تحتوي فئة GridViewColumn نفسها على الكثير من الخصائص، لذا قد ترغب في إضافة بعض المعلومات هناك باستخدام الخصائص المرفقة - على سبيل المثال.مثل علامة العمود الفريدة - من المرجح أن يتم استخدام الرأس للترجمة، ولن تقوم بالترحيل على هذا الرأس.

بشكل عام، هذا الأسلوب، على الرغم من كونه معقدًا للغاية، سيسمح لك بتوسيع وظيفة عرض القائمة بسهولة.

نصائح أخرى

يمكنك إضافة أعمدة بشكل حيوي إلى ListView باستخدام الخصائص المرفقة.راجع هذا المقال على CodeProject ويوضح ذلك بالضبط...

WPF DynamicListView - ربط DataMatrix

من MSDN:

    MyListBox.ItemsSource = view;
    ListView myListView = new ListView();

    GridView myGridView = new GridView();
    myGridView.AllowsColumnReorder = true;
    myGridView.ColumnHeaderToolTip = "Employee Information";

    GridViewColumn gvc1 = new GridViewColumn();
    gvc1.DisplayMemberBinding = new Binding("FirstName");
    gvc1.Header = "FirstName";
    gvc1.Width = 100;
    myGridView.Columns.Add(gvc1);
    GridViewColumn gvc2 = new GridViewColumn();
    gvc2.DisplayMemberBinding = new Binding("LastName");
    gvc2.Header = "Last Name";
    gvc2.Width = 100;
    myGridView.Columns.Add(gvc2);
    GridViewColumn gvc3 = new GridViewColumn();
    gvc3.DisplayMemberBinding = new Binding("EmployeeNumber");
    gvc3.Header = "Employee No.";
    gvc3.Width = 100;
    myGridView.Columns.Add(gvc3);

    //ItemsSource is ObservableCollection of EmployeeInfo objects
    myListView.ItemsSource = new myEmployees();
    myListView.View = myGridView;
    myStackPanel.Children.Add(myListView);

عند DataTemplateselector لتحديد أحد القوالب المحددة مسبقًا (من نفس نوع البيانات) وتطبيق المحدد على ListView.يمكن أن يكون لديك أكبر عدد ممكن من DataTemplates بأعمدة مختلفة.

يمكنك استخدام أ محدد قالب البيانات لإرجاع DataTemplate الذي قمت بإنشائه ديناميكيًا في التعليمات البرمجية.ومع ذلك، هذا أمر ممل بعض الشيء وأكثر تعقيدًا من استخدام واحد محدد مسبقًا من XAML، لكنه لا يزال ممكنًا.ألقِ نظرة على هذا المثال: http://dedjo.blogspot.com/2007/03/creating-datatemplates-from-code.html

من خلال الخبرة، يمكنني أن أوصي بالابتعاد عن قوالب البيانات الديناميكية إذا كان بإمكانك مساعدتها...بدلاً من ذلك، استخدم النصيحة المقدمة هنا لإنشاء أعمدة ListView بشكل صريح، بدلاً من محاولة إنشاء DataTemplate ديناميكيًا.

السبب هو أن FrameworkElementFactory (أو أيًا كان اسم الفئة لإنتاج DataTemplates في وقت التشغيل) غير مريح إلى حد ما في الاستخدام (وتم إهماله لصالح استخدام XAML للقوالب الديناميكية) - وفي كلتا الحالتين ستحقق نجاحًا كبيرًا في الأداء.

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