WPFのListViewやDataGridには列を固定する機能が用意されていないらしい。
Excelでいうところの「ウインドウ枠の固定」、WinFormsなら DataGridViewColumn.Frozen = True
にあたる機能。
StackOverflowにも質問が上がってるけど、回答としては「ListView2つ並べればいいんじゃねーの」とのこと。
それもちょっとなあという感じ。
必要になりそうなので、ItemsControlの勉強をかねて作ってみた。
https://github.com/wonderful-panda/playground.wpf
サンプル
こんな感じのアレとアレで、
MainViewModel.cs
public class File
{
public string Name { get; private set; }
public string Path { get; private set; }
public long Size { get; private set; }
public DateTime LastWriteTime { get; private set; }
public File(FileInfo fi)
{
this.Name = fi.Name;
this.Path = System.IO.Path.GetDirectoryName(fi.FullName);
this.Size = fi.Length;
this.LastWriteTime = fi.LastWriteTime;
}
}
public class MainWindowViewModel
{
public ObservableCollection<File> Files { get; private set; }
public MainWindowViewModel()
{
var directory = new DirectoryInfo(Environment.CurrentDirectory);
this.Files = new ObservableCollection<File>(directory.GetFiles().Select(fi => new File(fi)));
}
}
MainWindow.xaml
<Window x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:Test"
xmlns:c="clr-namespace:Playground.Controls;assembly=Playground.Controls"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<l:MainWindowViewModel x:Key="viewmodel" />
</Window.Resources>
<Window.DataContext>
<Binding Source="{StaticResource viewmodel}" />
</Window.DataContext>
<Grid>
<c:GridViewEx ItemsSource="{Binding Files}">
<c:GridViewEx.FrozenColumns>
<GridViewColumnCollection>
<GridViewColumn Header="ファイル名"
DisplayMemberBinding="{Binding Name}" />
</GridViewColumnCollection>
</c:GridViewEx.FrozenColumns>
<c:GridViewEx.NormalColumns>
<GridViewColumnCollection>
<GridViewColumn Header="サイズ"
DisplayMemberBinding="{Binding Size}" />
<GridViewColumn Header="更新日時"
DisplayMemberBinding="{Binding LastWriteTime, StringFormat='yyyy/MM/dd HH:mm:ss'}"/>
<GridViewColumn Header="フォルダ"
DisplayMemberBinding="{Binding Path}" />
</GridViewColumnCollection>
</c:GridViewEx.NormalColumns>
</c:GridViewEx>
</Grid>
</Window>
説明
やってることは単純で、行ごとに GridViewRowPresenter
を2つずつ(固定列用とそれ以外用)配置して、スクロールバーのHorizontalOffset
にあわせて左Marginを調節してるだけです。
細かい作りこみはまだ全然甘いですが。
でも GridViewRowPresenterEx
みたいなクラスを作ってその中で頑張る方が筋がいい気もする。
関係ないけど~Exみたいな命名ちょっとアレですね。