DataGrid に新規追加行(NewItemPlaceholder)を表示する方法
WPF の DataGrid に新規追加の行(NewItemPlaceholder)が表示されなくて数日はまったので、解決方法のメモ。新規追加の行と言ってるのは、ユーザがアイテムを新たに追加するためのプレースホルダのこと。表示される場合は、デフォルトでは空の行が表示されます。かっこ悪いです。
DataGrid に渡すデータはよっぽどのことがなければ ObservableCollection
マニュアルに書いといて欲しい…。
以上。で終わるのもなんなのでサンプル。
まずはダメな例。FileInfo には引数なしのコンストラクタがないので、これを DataGrid にバインディングしても新規追加の行は表示されません。
// ダメな例。DataGridに追加のための行が表示されない private ObservableCollection<FileInfo> dameCreateData() { var fs = Directory.GetFiles( "." ).Select( s => new FileInfo( s ) ); var data = new ObservableCollection<FileInfo>( fs ); return data; }
これを直して NewItemPlaceholder が表示されるようにするには、MVVM でいうところの ViewModel のようなクラス、つまり FileInfo をくるむラッパーを追加し、引数なしのコンストラクタを用意します。面倒です。やってられませんw
public class FileInfoViewModel : INotifyPropertyChanged { private FileInfo fileInfo; // 引数なしのコンストラクタ public FileInfoViewModel() : this( @"C:\pagefile.sys" ) {} public FileInfoViewModel( string fileName ) { this.fileInfo = new FileInfo( fileName ); } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged( string propertyName ) { if ( this.PropertyChanged != null ) { this.PropertyChanged( this, new PropertyChangedEventArgs( propertyName ) ); } } public string Name { get { return this.fileInfo.Name; } set { this.fileInfo = new FileInfo( value ); OnPropertyChanged( "Name" ); OnPropertyChanged( "Length" ); OnPropertyChanged( "CreationTime" ); OnPropertyChanged( "LastAccessTime" ); } } public long Length { get { return this.fileInfo.Length; } } public DateTime CreationTime { get { return this.fileInfo.CreationTime; } set { this.fileInfo.CreationTime = value; OnPropertyChanged( "CreationTime" ); } } public DateTime LastAccessTime { get { return this.fileInfo.LastAccessTime; } } }
超超手抜きでもこんなに長い。だるい。MVVM って本気なの?M なの?
これを使って、先のダメな例を書き直す。
private ObservableCollection<FileInfoViewModel> CreateData() { var fs = Directory.GetFiles( "." ).Select( s => new FileInfoViewModel( s ) ); var data = new ObservableCollection<FileInfoViewModel>( fs ); return data; }
あとは this.DataContext = CreateData(); として DataGrid に渡すだけ。
<Window x:Class="DataGridTest.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:tk="http://schemas.microsoft.com/wpf/2008/toolkit" Title="Window1" Height="300" Width="800"> <Grid> <tk:DataGrid ItemsSource="{Binding}" /> </Grid> </Window>
これでユーザーが追加できるようになります。
WPF の DataGrid について
- DataGrid は今は http://wpf.codeplex.com/ の WPF Toolkit にあります。3ヶ月ごとに出てるので今月も出るかも。.NET4.0 には追加される予定。
- マニュアル。
- かっこ悪いデフォルトの追加行(空行)を置き換えるサンプルはこちら。