[WPF/xaml] ListViewのGrid表示のセルの中身をカスタムする


もくじ

やりたいこと

GridのListView表示の、セルの中を好きなようにいじりたい。
下記のようなイメージ。

やりかた

<GridViewColumn.CellTemplate>を使う。

サンプル

MainWindow.xaml
<Window x:Class="ListViewTet.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ListViewTet"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <ListView ItemsSource="{Binding DataList}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="色" DisplayMemberBinding="{Binding No}" Width="80" />
                    <GridViewColumn Header="コード" Width="80" >
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal">
                                    <TextBlock Text="{Binding Brush}" />
                                    <Rectangle Fill="{Binding Brush}" Width="10" Height="10"/>
                                </StackPanel>
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                </GridView>
            </ListView.View>
        </ListView>
    </Grid>
</Window>

MainWindow.xaml.cs
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Media;

namespace ListViewTet
{
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName) => this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        #endregion

        public ObservableCollection<MyData> DataList { get; set; } = new ObservableCollection<MyData>();

        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;

            DataList.Add(new MyData() { No = 1, Brush = new SolidColorBrush(Colors.Red) });
            DataList.Add(new MyData() { No = 2, Brush = new SolidColorBrush(Colors.Blue) });
            DataList.Add(new MyData() { No = 3, Brush = new SolidColorBrush(Colors.Green) });
        }
    }

    public class MyData
    {
        public int No { get; set; }
        public SolidColorBrush Brush { get; set; }
    }
}

注意

下記のページで勉強させていただいた内容。

DisplayMemberBindingとCellTemplate

<GridViewColumn >に、ListViewのItemsTemplateにバインドしたコレクションのプロパティを表示したいだけならDisplayMemberBindingにプロパティをバインドする。
(サンプルプログラムのHeader="色"の列を参照)

列のセルをいろいろ変えたいなら、<GridViewColumn >DisplayMemberBindingに値をセット「せずに」、<GridViewColumn.CellTemplate><DataTemplate>をセットする。
(サンプルプログラムのHeader="コード"の列を参照)

DisplayMemberBindingになにかバインドしてると、<DataTemplate>にセットした内容が反映されてくれないらしい。

追記
下記のページに、その辺の優先順位が書いていた。

styleがない

GridView や GridViewColumn はFrameworkElement を継承していないので、styleをもっておらず、同じ見た目の列を作りたいと思ってもリソースでstyleを作ってそれを使いまわすということができない様子。

参考

公式 GridView(ListViewのモードの一種)のカスタムの仕方