【问题标题】:Create WPF ItemTemplate DYNAMICALLY at runtime在运行时动态创建 WPF ItemTemplate
【发布时间】:2008-09-24 06:04:27
【问题描述】:

在运行时,我想在 WPF ListView 中动态构建网格列(或其他显示布局)。我事先不知道列的数量和名称。

我希望能够做到:
MyListView.ItemSource = 我的数据集;
MyListView.CreateColumns();

【问题讨论】:

    标签: wpf listview


    【解决方案1】:

    您可以使用附加属性将列动态添加到 ListView。查看 CodeProject 上的这篇文章,它准确地解释了...

    WPF DynamicListView - Binding to a DataMatrix

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        我会尝试以下方法:

        A)您需要让列表框显示网格视图 - 我相信您已经这样做了
        B) 为 GridViewColumnHeader 定义样式:

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

        在我的情况下,我设置了一大堆其他属性,但在基本场景中 - 你需要 Loaded 事件。单击 - 如果您想添加排序和过滤功能,这很有用。

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

                    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 类本身没有太多属性,因此您可能希望使用附加属性在其中添加一些信息 - 即像唯一的列标签 - 标题很可能会用于本地化,您不会在此进行中继.

        一般来说,这种方法虽然相当复杂,但可以让您轻松扩展列表视图功能。

        【讨论】:

          【解决方案4】:

          有一个 DataTemplateselector 来选择一个预定义的模板(相同的 DataType)并将选择器应用到 ListView。您可以拥有尽可能多的具有不同列的 DataTemplate。

          【讨论】:

          • 我不知道之前列的编号或名称 - 这有什么帮助?
          【解决方案5】:

          您可以使用 DataTemplateSelector 来返回您在代码中动态创建的 DataTemplate。但是,这比使用 XAML 中的预定义有点繁琐且复杂,但它仍然是可能的。 看看这个例子:http://dedjo.blogspot.com/2007/03/creating-datatemplates-from-code.html

          【讨论】:

            【解决方案6】:

            根据经验,如果您能提供帮助,我建议您不要使用动态数据模板...而是使用此处给出的建议来显式创建 ListView 列,而不是尝试动态创建 DataTemplate。

            原因是 FrameworkElementFactory(或任何用于在运行时生成 DataTemplates 的类名)使用起来有些笨拙(并且不推荐使用 XAML 来生成动态模板)——无论哪种方式都会对性能造成影响。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2020-05-04
              • 1970-01-01
              • 1970-01-01
              • 2011-03-07
              • 2010-09-07
              • 2017-09-24
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多