質問

実行時に、WPF ListView でグリッド列 (または別の表示レイアウト) を動的に構築したいと考えています。列の番号と名前が事前にわかりません。

できるようになりたい:
MyListView.ItemSource = MyDataset;
MyListView.CreateColumns();

役に立ちましたか?

解決

次のアプローチを試してみます:

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 クラス自体には多くのプロパティがないため、添付プロパティを使用してそこに情報を追加することもできます。固有の列タグと同様に、ヘッダーはローカリゼーションに使用される可能性が高く、これについては中継しません。

一般に、このアプローチでは、非常に複雑ではありますが、リスト ビューの機能を簡単に拡張できます。

他のヒント

添付プロパティを使用して、ListView に列を動的に追加できます。この記事をチェックしてください コードプロジェクト それはまさにそれを説明しています...

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

持っています データテンプレートセレクター (同じデータ型の) 定義済みテンプレートの 1 つを選択し、セレクターを ListView に適用します。異なる列を持つ DataTemplate をいくつでも持つことができます。

を使用できます データテンプレートセレクター コードで動的に作成した DataTemplate を返します。ただし、これは少し面倒で、XAML の事前定義されたものを使用するよりも複雑ですが、それでも可能です。この例を見てください。 http://dedjo.blogspot.com/2007/03/creating-datatemplates-from-code.html

経験上、できる限り動的データ テンプレートを避けることをお勧めします...DataTemplate を動的に作成しようとするのではなく、ここで提供されているアドバイスを使用して、ListView 列を明示的に作成してください。

その理由は、FrameworkElementFactory (または実行時に DataTemplate を生成するためのクラス名) がやや使いにくいため (動的テンプレートには XAML を使用することが推奨され、非推奨になっています)、どちらにしてもパフォーマンスが低下します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top