◆ GridView/GridViewColumn が Style や Resources を持てない
◆ デフォルトデザインが設定できない 

ListView の GridView を使った表形式表示についてです

GridView

GridView を使った ListView では ListView.View に表示方法を定義した GridView を設定します
データは ListView.ItemsSource プロパティにコレクションをセットします

GridView には列 (GridViewColumn) を設定して GridViewColumn に ItemsSource で設定した各要素(行) から Binding するプロパティやそのデータを表示するテンプレートなどを設定します

こういうの
<ListView ItemsSource="{Binding items}">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="No." DisplayMemberBinding="{Binding num}" Width="80" />
            <GridViewColumn Header="名前" DisplayMemberBinding="{Binding name}" Width="80" />
        </GridView>
    </ListView.View>
</ListView>


表示したい列の情報を設定しておいて そこにデータを入れたらいい感じに表示してくれるものです

GridViewColumn が Style をもてない

一見便利そうなんですけど GridView や GridViewColumn は他のコントロールとちょっと違い FrameworkElement を継承してません

そのせいで Style や Resources プロパティがありません


Style や Resources がないということは App.xaml でデフォルトスタイルを設定ができないということになります
すべての ListView に対して設定したいテンプレートがあるなら毎回コピペで同じことを書かないといけないです

例1

例えば 「この ListView は全部の列で」 文字色を green にしようとしたらこうなります
<ListView ItemsSource="{Binding items}">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="No." Width="80">
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding num}" Foreground="green" />
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
            <GridViewColumn Header="名前" Width="80">
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding name}" Foreground="green" />
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
        </GridView>
    </ListView.View>
</ListView>

全部に CellTemplate を設定しています
すごく  めんどくさいです

せめてリソースにまとめたいのですが Binding 対象も CellTemplate で設定しているので 列ごとに表示する項目が違うと使えません
<ListView ItemsSource="{Binding items}">
    <ListView.Resources>
        <DataTemplate x:Key="tpl">
            <TextBlock Text="{Binding num}" Foreground="green" />
        </DataTemplate>
    </ListView.Resources>
    <ListView.View>
        <GridView>
            <GridViewColumn Header="No." CellTemplate="{StaticResource tpl}" Width="80" />
        </GridView>
    </ListView.View>
</ListView>

tpl を他の列に使うとそこでも num プロパティの値が表示されてしまいます


本当に ListView 全部の列の色を変えるなら ListView 自体や各行の ListViewItem に Style 当てれば済みますけどね
<ListView.Resources>
    <Style TargetType="ListView">
        <Setter Property="Foreground" Value="red"/>
    </Style>
</ListView.Resources>
<ListView.Resources>
    <Style TargetType="ListViewItem">
        <Setter Property="Foreground" Value="red"/>
    </Style>
</ListView.Resources>

例2

全部変えるというより GridViewColumn に添付プロパティで状態をセットしておいて 状態によって背景色を変えるなどの設定をしたいときのほうがこまります

トリガを設定したいのに Style がないですから設定できません

DataTemplate の方のルート要素に指定するにも GridViewColumn の添付プロパティを Template 内から知るのが難しいです
Converter の中であれこれがんばって 添付プロパティを取り出してトリガのキーにできても そこまでするなら 最初から添付プロパティを C# コードで設定するのじゃなくて 直接スタイルを全部のセルに当ててしまえばいいようにも思えてきます


簡単にできそうなことなのにできないのは GridViewColumn が Style を持たない特殊な仕様だからです

実体がないのは仕方ないにしても なんらかの方法を用意してほしいですよ
ListView は DataGrid と違って機能もシンプルだから自分でつくって というスタイルなんでしょうかねー

DisplayMemberBinding と CellTemplate

両方一緒につかってはいけません


これのせいで数十分ハマってました

DisplayMemberBinding があると CellTemplate は無視されます

DisplayMemberBinding

一般的にこっち使ってるのが多いと思います

ListView の ItemsSource に設定したコレクションのそれぞれ(行)のオブジェクトに対して表示するプロパティを指定するもの
<GridViewColumn DisplayMemberBinding="{Binding name}" />
と書くと この列のそれぞれの行に表示するデータは オブジェクトの name プロパティになります

CellTemplate

こっちは詳しくデザイン設定するテンプレートを指定します
ただ Style がないので 本来は Style だけでいい色を変えたりフォントサイズを変えるだけでも Template を使わないといけません
<GridViewColumn>
    <GridViewColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding num}" Foreground="green" />
        </DataTemplate>
    </GridViewColumn.CellTemplate>
</GridViewColumn>

シンプルにテキストを表示するだけなら TextBlock に Binding すればおっけいです
ここでの Binding は DisplayMemberBinding と一緒のものです

混ぜるとテンプレート使ってくれない

CellTemplate は全然使うことがなかったので なんとなーくな記憶だったので 文字色だけ変えようってときは DisplayMemberBinding でデータを決めて 色だけを CellTemplate で変えればいいと思っていました

CellTemplate の Binding で気づけそうですが たまたま見てたサンプルが {Binding} だったので DisplayMemberBinding で Binding した値が {Bindng} で設定されるんだなと思いこんでました

そのせいで
<GridViewColumn DisplayMemberBinding="{Binding name}">
    <GridViewColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding}" Foreground="green" />
        </DataTemplate>
    </GridViewColumn.CellTemplate>
</GridViewColumn>

と書いて 全然色つかない! と思って次に
<GridViewColumn DisplayMemberBinding="{Binding name}">
    <GridViewColumn.CellTemplate>
        <DataTemplate>
            <Button />
        </DataTemplate>
    </GridViewColumn.CellTemplate>
</GridViewColumn>

にしてみても name がでていてボタンが出ないので バグってるんじゃないの と思って VisualStudio を再起動する始末……

両方使えませんって注意書きでればいいんですけどねー

みなさんも気をつけてください