none
WPF Listviewのヘッダー表示のカスタマイズ RRS feed

  • 質問

  • Listviewをカスタマイズし、カラムヘッダー名(GridViewColumn.header)と付加情報を上下に並べて表示したいと考えています。
    サンプルソースでは、ヘッダーの中で上下にLabelを配置し、上段にカラムヘッダー名(これはスタティックなテキストです。)、下段に付加情報をContentで表示させるようにしています。
    付加情報をコントロールするために、GridViewColumnを継承したクラスを作成し、GridViewColumn.headerと同じ手続きで使えるGridViewColumn.header2というプロパティーを付加しています。
    Visual Basic側では、myGridView.Columns(1).header2="lower header"などとして付加情報をダイナミックに変更したいと考えています。

    分からないのはXAML側の書き方です。
    <DataTemplate x:Key="MyTemp0">の中でLabelを2つ配置しています。
    上のLabelのContentは、Content="{Binding}"としてカラムヘッダー名をバインドしています。(この方法はあるWEBサイトから見つけましたが、なぜこれだけの記述でGridViewColumn.headerがバインドされるのか、これについても同時に御教授をお願いします。)
    下のLabelではContent="header2"と固定表示になっていますが、myGridView.Columns(n).header2をバインドしてVBからContentを操作するには、どうしたら良いのでしょうか。
    御回答をお願いします。
    開発環境 Visual Studio 2010 Professional

    VBソースコード↓


    Class MainWindow

        Public Class GridViewColumn_u ’ユーザー定義のGridViewColumnクラス
            Inherits GridViewColumn
            Public Property header2 As String
        End Class

        Private Sub MainWindow_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded

            Dim myGridView As New GridView()

            Dim gvc0 As GridViewColumn_u
            gvc0 = New GridViewColumn_u()
            gvc0.Header = "Column1"
        gvc0.Header2 = "2nd Line"
            gvc0.Width = 100
            myGridView.Columns.Add(gvc0)
            myGridView.Columns(0).HeaderTemplate = CType(Me.ListView1.FindResource("MyTemp0"), System.Windows.DataTemplate)
            Me.ListView1.View = myGridView

        End Sub

    End Class

    ----
    XAML↓
    ----

    <Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
       
        <StackPanel Height="305" Name="StackPanel1" Width="439" >
            <ListView Height="98" Name="ListView1" Width="269" VerticalAlignment="Top"
                <ListView.Resources>
                    <!-- Listview 個別のheaderに対するテンプレート -->
                    <DataTemplate x:Key="MyTemp0">
                        <StackPanel Orientation="Vertical" x:Name="stack0">
                            <Label Content="{Binding}" Background="#FFD82121" Width="70"> </Label>
                            <Label Content="header2" Background="#FFE89B3E" Width="70"  > </Label>
                        </StackPanel>
                    </DataTemplate>
                </ListView.Resources>
            </ListView>
        </StackPanel>
    </Window>

    2011年11月27日 9:58

回答

  • こんな?

    <Window x:Class="MainWindow1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
        <Grid>
            <StackPanel Height="305" Name="StackPanel1" Width="439" >
                <ListView Height="98" Name="ListView1" Width="269" VerticalAlignment="Top">
                    <ListView.Resources>
                        <!-- Listview 個別のheaderに対するテンプレート -->
                        <DataTemplate x:Key="MyTemp0">
                            <StackPanel Orientation="Vertical" x:Name="stack0">
                                <Label Content="{Binding HeaderText1}" Background="#FFD82121" Width="70"></Label>
                                <Label Content="{Binding HeaderText2}" Background="#FFE89B3E" Width="70"  
                               x:Name="HeaderLabel2" />
                            </StackPanel>
                        </DataTemplate>
                    </ListView.Resources>
                </ListView>
            </StackPanel>
        </Grid>
    </Window>
    

    Class MainWindow1
    
        Public Class ColumnHeaderData
            Implements System.ComponentModel.INotifyPropertyChanged
    
            Private _HeaderText1 As String
    
            Public Property HeaderText1() As String
                Get
                    Return _HeaderText1
                End Get
                Set(ByVal value As String)
                    _HeaderText1 = value
                    OnPropertyChanged("HeaderText1")
                End Set
            End Property
    
    
            Private _HeaderText2 As String
            Public Property HeaderText2() As String
                Get
                    Return _HeaderText2
                End Get
                Set(ByVal value As String)
                    _HeaderText2 = value
                    OnPropertyChanged("HeaderText2")
                End Set
            End Property
    
            Public Overrides Function ToString() As String
                Return HeaderText1
            End Function
    
            Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
            Protected Sub OnPropertyChanged(ByVal name As String)
                RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(name))
            End Sub
        End Class
    
        Public Class GridViewColumn_u 'ユーザー定義のGridViewColumnクラス
            Inherits GridViewColumn
    
            Public Sub New()
                Me.Header = New ColumnHeaderData()
            End Sub
    
            Public ReadOnly Property ColumnHeaderData() As ColumnHeaderData
                Get
                    Dim data As ColumnHeaderData = TryCast(Me.Header, ColumnHeaderData)
                    If data Is Nothing Then
                        data = New ColumnHeaderData()
                        Me.Header = data
                    End If
                    Return data
                End Get
            End Property
        End Class
    
        Private Sub MainWindow_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
    
            Dim myGridView As New GridView()
    
            headerData = New ColumnHeaderData
            headerData.HeaderText1 = "Column1"
            headerData.HeaderText2 = "2ndLine"
    
            Dim gvc0 As New GridViewColumn
            gvc0.Header = headerData
            gvc0.Width = 100
            myGridView.Columns.Add(gvc0)
    
            Dim template As DataTemplate
            template = CType(Me.ListView1.FindResource("MyTemp0"), System.Windows.DataTemplate)
    
            Dim gvc1 As New GridViewColumn_u
            gvc1.Width = 100
            gvc1.ColumnHeaderData.HeaderText1 = "いろはにほ"
            gvc1.ColumnHeaderData.HeaderText2 = Date.Now.ToString
            myGridView.Columns.Add(gvc1)
    
            myGridView.Columns(0).HeaderTemplate = template
            myGridView.Columns(1).HeaderTemplate = template
    
            Me.ListView1.View = myGridView
    
        End Sub
    
        Private headerData As ColumnHeaderData
    
        Private Sub ListView1_MouseDoubleClick(ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseButtonEventArgs) Handles ListView1.MouseDoubleClick
            headerData.HeaderText1 = "あいうえお"
            headerData.HeaderText2 = "かきくけこ"
    
            Dim gridView As GridView = CType(Me.ListView1.View, GridView)
            Dim column1 As GridViewColumn_u = CType(gridView.Columns(1), GridViewColumn_u)
            column1.ColumnHeaderData.HeaderText1 = "ABCD"
            column1.ColumnHeaderData.HeaderText2 = "12345"
        End Sub
    End Class
    


    上のLabelのContentは、Content="{Binding}"としてカラムヘッダー名をバインドしています。(この方法はあるWEBサイトから見つけましたが、なぜこれだけの記述でGridViewColumn.headerがバインドされるのか、これについても同時に御教授をお願いします。)

    GridViewColumnのHeaderプロパティにセットしてあるデータが、DataTemplateで生成されたヘッダーの中身のDataContextになるからです。
    そのためPathを指定してないBindingではその文字列が表示されます。
    #文字列でないときはLabelで文字列になるように変換される

    ここで、GridViewColumnのHeaderプロパティに文字以外のデータ(上記コードではColumnHeaderDataクラス)を入れてやることで複数の内容をヘッダーの内側に伝えることができます。

    GridViewColumn.headerと同じ手続きで使えるGridViewColumn.header2というプロパティーを付加しています。
    XAML側でも同じ手続きにするにはDependencyPropertyにする必要があるので、ちょっと面倒になります。
    継承とか考えずにHeaderプロパティに入れるデータのほうを変えたほうが楽ですよ。

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
    • 回答としてマーク 馋涎欲滴 2011年11月28日 13:14
    2011年11月27日 11:55

すべての返信

  • こんな?

    <Window x:Class="MainWindow1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
        <Grid>
            <StackPanel Height="305" Name="StackPanel1" Width="439" >
                <ListView Height="98" Name="ListView1" Width="269" VerticalAlignment="Top">
                    <ListView.Resources>
                        <!-- Listview 個別のheaderに対するテンプレート -->
                        <DataTemplate x:Key="MyTemp0">
                            <StackPanel Orientation="Vertical" x:Name="stack0">
                                <Label Content="{Binding HeaderText1}" Background="#FFD82121" Width="70"></Label>
                                <Label Content="{Binding HeaderText2}" Background="#FFE89B3E" Width="70"  
                               x:Name="HeaderLabel2" />
                            </StackPanel>
                        </DataTemplate>
                    </ListView.Resources>
                </ListView>
            </StackPanel>
        </Grid>
    </Window>
    

    Class MainWindow1
    
        Public Class ColumnHeaderData
            Implements System.ComponentModel.INotifyPropertyChanged
    
            Private _HeaderText1 As String
    
            Public Property HeaderText1() As String
                Get
                    Return _HeaderText1
                End Get
                Set(ByVal value As String)
                    _HeaderText1 = value
                    OnPropertyChanged("HeaderText1")
                End Set
            End Property
    
    
            Private _HeaderText2 As String
            Public Property HeaderText2() As String
                Get
                    Return _HeaderText2
                End Get
                Set(ByVal value As String)
                    _HeaderText2 = value
                    OnPropertyChanged("HeaderText2")
                End Set
            End Property
    
            Public Overrides Function ToString() As String
                Return HeaderText1
            End Function
    
            Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
            Protected Sub OnPropertyChanged(ByVal name As String)
                RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(name))
            End Sub
        End Class
    
        Public Class GridViewColumn_u 'ユーザー定義のGridViewColumnクラス
            Inherits GridViewColumn
    
            Public Sub New()
                Me.Header = New ColumnHeaderData()
            End Sub
    
            Public ReadOnly Property ColumnHeaderData() As ColumnHeaderData
                Get
                    Dim data As ColumnHeaderData = TryCast(Me.Header, ColumnHeaderData)
                    If data Is Nothing Then
                        data = New ColumnHeaderData()
                        Me.Header = data
                    End If
                    Return data
                End Get
            End Property
        End Class
    
        Private Sub MainWindow_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
    
            Dim myGridView As New GridView()
    
            headerData = New ColumnHeaderData
            headerData.HeaderText1 = "Column1"
            headerData.HeaderText2 = "2ndLine"
    
            Dim gvc0 As New GridViewColumn
            gvc0.Header = headerData
            gvc0.Width = 100
            myGridView.Columns.Add(gvc0)
    
            Dim template As DataTemplate
            template = CType(Me.ListView1.FindResource("MyTemp0"), System.Windows.DataTemplate)
    
            Dim gvc1 As New GridViewColumn_u
            gvc1.Width = 100
            gvc1.ColumnHeaderData.HeaderText1 = "いろはにほ"
            gvc1.ColumnHeaderData.HeaderText2 = Date.Now.ToString
            myGridView.Columns.Add(gvc1)
    
            myGridView.Columns(0).HeaderTemplate = template
            myGridView.Columns(1).HeaderTemplate = template
    
            Me.ListView1.View = myGridView
    
        End Sub
    
        Private headerData As ColumnHeaderData
    
        Private Sub ListView1_MouseDoubleClick(ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseButtonEventArgs) Handles ListView1.MouseDoubleClick
            headerData.HeaderText1 = "あいうえお"
            headerData.HeaderText2 = "かきくけこ"
    
            Dim gridView As GridView = CType(Me.ListView1.View, GridView)
            Dim column1 As GridViewColumn_u = CType(gridView.Columns(1), GridViewColumn_u)
            column1.ColumnHeaderData.HeaderText1 = "ABCD"
            column1.ColumnHeaderData.HeaderText2 = "12345"
        End Sub
    End Class
    


    上のLabelのContentは、Content="{Binding}"としてカラムヘッダー名をバインドしています。(この方法はあるWEBサイトから見つけましたが、なぜこれだけの記述でGridViewColumn.headerがバインドされるのか、これについても同時に御教授をお願いします。)

    GridViewColumnのHeaderプロパティにセットしてあるデータが、DataTemplateで生成されたヘッダーの中身のDataContextになるからです。
    そのためPathを指定してないBindingではその文字列が表示されます。
    #文字列でないときはLabelで文字列になるように変換される

    ここで、GridViewColumnのHeaderプロパティに文字以外のデータ(上記コードではColumnHeaderDataクラス)を入れてやることで複数の内容をヘッダーの内側に伝えることができます。

    GridViewColumn.headerと同じ手続きで使えるGridViewColumn.header2というプロパティーを付加しています。
    XAML側でも同じ手続きにするにはDependencyPropertyにする必要があるので、ちょっと面倒になります。
    継承とか考えずにHeaderプロパティに入れるデータのほうを変えたほうが楽ですよ。

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
    • 回答としてマーク 馋涎欲滴 2011年11月28日 13:14
    2011年11月27日 11:55
  • とても良く理解できました!
    ヘッダーを2行にしたほか、従来のWindows.formでのListviewでヘッダーをクリックしてソートする毎にヘッダー右端の▼/▲の表示を入れ替える動作も実現できました。
    私は、難題にぶつかったときはまずWEBサイトを入念に検索して解決方法を探し出していますが、WPFで小細工するにしても情報が少な過ぎ、どうにもならないことがしばしばです。今後も時に応じて質問させていただきますので、初学者の私に皆様どうかよろしくご協力をお願い致します。

    gekkaさん、大変感謝致します。

    2011年11月28日 13:25