Создавайте WPF ItemTemplate ДИНАМИЧЕСКИ во время выполнения

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

  •  02-07-2019
  •  | 
  •  

Вопрос

Во время выполнения я хочу динамически создавать столбцы сетки (или другой макет отображения) в WPF ListView.Я не знаю количества и названий столбцов, находящихся под рукой.

Я хочу быть в состоянии делать:
MyListView.ItemSource = Набор моих данных;
MyListView.Создайте столбцы ();

Это было полезно?

Решение

я бы попробовал следующий подход:

A) вам нужно, чтобы окно списка отображало сетку - я полагаю, это вы уже сделали
Б) определите стиль для GridViewColumnHeader:

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

в моем случае у меня была установлена целая куча других свойств, но в базовом сценарии вам понадобилось бы Загруженное событие.Нажал - это полезно, если вы хотите добавить функции сортировки и фильтрации.

C) в вашем коде listview привяжите шаблон к вашему gridview:

    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");
        }
    }

D) затем в вашем обработчике OnHeaderLoaded вы можете установить соответствующий шаблон на основе данных столбца

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

// выберите и примените свой шаблон данных здесь.

        e.Handled = true;
    }

E) Я предполагаю, что вам также нужно было бы приобрести право собственности на свойство зависимости 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, используя прикрепленные свойства.Ознакомьтесь с этой статьей о Кодовый проект это именно это и объясняет...

WPF DynamicListView - Привязка к матрице данных

Из 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.У вас может быть столько табличек данных с разными столбцами.

Вы можете использовать DataTemplateSelector - Выбор данных чтобы вернуть DataTemplate, который вы создали динамически в коде.Однако это немного утомительно и сложнее, чем использование предопределенного из XAML, но это все еще возможно.Взгляните на этот пример: http://dedjo.blogspot.com/2007/03/creating-datatemplates-from-code.html

Исходя из опыта, я могу порекомендовать избегать динамических шаблонов данных, если вы можете помочь этому...лучше воспользуйтесь приведенным здесь советом, чтобы явно создать столбцы ListView, а не пытаться динамически создавать DataTemplate.

Причина в том, что FrameworkElementFactory (или как бы там ни назывался класс для создания DataTemplates во время выполнения) несколько неудобен в использовании (и устарел в пользу использования XAML для динамических шаблонов) - в любом случае вы снижаете производительность.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top