在运行时动态创建WPF ItemTemplate

sgtfey8w  于 2022-11-18  发布在  其他
关注(0)|答案(7)|浏览(260)

在运行时,我想在WPF ListView中动态生成网格列(或其他显示布局)。我事先不知道列的编号和名称。
我希望能够做到:
我的列表视图.项源=我的数据集;
创建列();

sshcrbum

sshcrbum1#

您可以使用[附加属性]将数据行动态加入至ListView。请参阅CodeProject上的这篇文章,它会详细说明...
WPF DynamicListView - Binding to a DataMatrix

8fsztsew

8fsztsew2#

来自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);
np8igboo

np8igboo3#

我会尝试以下方法:
A)您需要让列表框显示网格视图-我相信您已经做到了这一点
B)为GridViewColumnHeader定义一个样式:

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

在我的例子中,我设置了一大堆其他属性,但在基本场景中-您需要Loaded event. Clicked -如果您希望添加排序和筛选功能,这将非常有用。
C)在你的列表视图代码中,将模板与你的网格视图绑定:

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依赖项属性的所有权并处理它的changed事件。

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类本身没有太多属性,因此您可能希望使用附加属性在其中添加一些信息-例如,像唯一的列标记- header很可能用于本地化,您将不使用此属性。
一般来说,这种方法虽然相当复杂,但可以让您轻松地扩展列表视图功能。

31moq8wy

31moq8wy4#

使用DataTemplateselector选择一个预定义的模板(属于相同的DataType)并将选择器应用于ListView。可以使用具有不同列的任意多个DataTemplate。

w9apscun

w9apscun5#

您可以使用DataTemplateSelector返回您在代码中动态创建的DataTemplate。但是,这比使用XAML中的预定义模板要繁琐和复杂一些,但仍然是可能的。请看下面的示例:http://dedjo.blogspot.com/2007/03/creating-datatemplates-from-code.html

gkl3eglg

gkl3eglg6#

根据经验,我建议您尽量避免使用动态数据模板.... a.而不是使用此处给出的建议来显式创建ListView列,而不是尝试动态创建DataTemplate。
原因是FrameworkElementFactory(或在运行时生成DataTemplates的任何类名)使用起来有些笨拙(并且不赞成使用XAML作为动态模板)-无论哪种方式都会对性能造成影响。

s6fujrry

s6fujrry7#

此函数将将列绑定到指定的类,并动态设置标题、绑定、宽度和字符串格式。

private void AddListViewColumns<T>(GridView GvFOO)
    {
        foreach (System.Reflection.PropertyInfo property in typeof(T).GetProperties().Where(p => p.CanWrite)) //loop through the fields of the object
        {
            if (property.Name != "Id") //if you don't want to add the id in the list view
            {
                GridViewColumn gvc = new GridViewColumn(); //initialize the new column
                gvc.DisplayMemberBinding = new Binding(property.Name); // bind the column to the field
                if (property.PropertyType == typeof(DateTime)) { gvc.DisplayMemberBinding.StringFormat = "yyyy-MM-dd"; } //[optional] if you want to display dates only for DateTime data
                gvc.Header = property.Name; //set header name like the field name
                gvc.Width = (property.Name == "Description") ? 200 : 100; //set width dynamically
                GvFOO.Columns.Add(gvc); //add new column to the Gridview
            }
        }
    }

假设您的XAML中有一个名称为“GvFoo”的GridView,您希望将其绑定到类FOO。然后,您可以通过将类“FOO”和GridView“GvFoo”作为参数传递到MainWindow.xaml.cs中来调用该函数**

AddLvTodoColumns<FOO>(GvFoo);

您的MainWindow.xaml文件应该包括以下内容

<ListView x:Name="LvFOO">
     <ListView.View>
          <GridView x:Name="GvTodos"/>
     </ListView.View>
 </ListView>

相关问题