Создавайте WPF ItemTemplate ДИНАМИЧЕСКИ во время выполнения
Вопрос
Во время выполнения я хочу динамически создавать столбцы сетки (или другой макет отображения) в 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, используя прикрепленные свойства.Ознакомьтесь с этой статьей о Кодовый проект это именно это и объясняет...
Из 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 для динамических шаблонов) - в любом случае вы снижаете производительность.