実行時に、WPF ListView でグリッド列 (または別の表示レイアウト) を動的に構築したいと考えています。列の数と名前は事前にわかりません。
私ができるようにしたい:
MyListView.ItemSource = MyDataset;
MyListView.CreateColumns();
添付プロパティを使用して、ListView に列を動的に追加できます。CodeProjectのこの記事をチェックしてください。それはまさにそれを説明しています...
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);
私は次のアプローチを試してみます:
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 クラス自体には多くのプロパティがないため、添付プロパティを使用してそこに情報を追加することをお勧めします。つまり、一意の列タグなどです。ヘッダーはローカリゼーションに使用される可能性が高く、これを中継しません。
一般に、この方法は非常に複雑ですが、リスト ビューの機能を簡単に拡張できます。
DataTemplateSelector を使用して、コードで動的に作成したDataTemplateを返すことができます。ただし、これは XAML から事前定義されたものを使用するよりも少し面倒で複雑ですが、それでも可能です。この例を見てください: http://dedjo.blogspot.com/2007/03/creating-datatemplates-from-code.html
経験から言えば、動的データ テンプレートを避けることをお勧めします。DataTemplate を動的に作成しようとするのではなく、ここで示したアドバイスを使用して ListView 列を明示的に作成してください。
その理由は、FrameworkElementFactory (または実行時に DataTemplate を生成するためのクラス名は何でも) を使用するのがやや厄介であるためです (動的テンプレートに XAML を使用することを支持して廃止されます) - どちらの方法でもパフォーマンスが低下します。
DataTemplateselectorを使用して、定義済みのテンプレート (同じ DataType) の 1 つを選択し、そのセレクターを ListView に適用します。異なる列を持つ DataTemplates をいくつでも持つことができます。