次の方法で共有


ListViewの表示が遅いです

質問

2009年4月23日木曜日 7:50 | 1 票

現在VS2008 C#にて開発を行っております。
ListView.ItemsSourceを使いSort処理の高速化は対応できたのですが、
Sort処理後から実際に表示されるまでに時間(2万データで50秒位)がかかってしまいます。

遅くなる原因をご教授頂けないでしょうか?

すべての返信 (27)

2009年5月8日金曜日 10:23 ✅回答済み | 1 票

すいません。
画面いっぱいに表示して試してたので気づきませんでした。
ItemsControlの高さを、Gridとあわせるようにしてみました。
これでどうでしょう。

                        <Grid HorizontalAlignment="Stretch" Margin="0,0,3,0" Name="body">
                            <ScrollContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="PART_ScrollContentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" CanContentScroll="{TemplateBinding CanContentScroll}" KeyboardNavigation.DirectionalNavigation="Local" />
                            <!-- 縦線の挿入 -->
                            <Canvas>
                                <ItemsControl Canvas.Left="{Binding HorizontalOffset, Mode=OneWay, Converter={StaticResource negativeConverter}, RelativeSource={RelativeSource TemplatedParent}}"
                                              IsHitTestVisible="False"
                                              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                              ItemsSource="{Binding Path=TemplatedParent.View.Columns, RelativeSource={RelativeSource TemplatedParent}}"
                                              Height="{Binding ElementName=body, Path=ActualHeight}"
                                              Width="{Binding ElementName=header, Path=ActualWidth}">
                                    <ItemsControl.ItemTemplate>
                                        <DataTemplate>
                                            <Border Width="{Binding Path=ActualWidth}" BorderThickness="0,0,1,0" BorderBrush="{DynamicResource verticalLineColor}" />
                                        </DataTemplate>
                                    </ItemsControl.ItemTemplate>
                                    <ItemsControl.ItemsPanel>
                                        <ItemsPanelTemplate>
                                            <StackPanel Orientation="Horizontal" />
                                        </ItemsPanelTemplate>
                                    </ItemsControl.ItemsPanel>
                                </ItemsControl>
                            </Canvas>
                        </Grid>

 

かずき Blog:http://blogs.wankuma.com/kazuki/


2009年4月24日金曜日 7:44

調べていてUpdateLayoutの処理に時間がかかっていることがわかりました。

UpdateLayoutが遅くなる原因をご教授頂けないでしょうか?


2009年4月24日金曜日 7:55

20000行だからってのは、答えにならないのかな・・
2万行分のレイアウトを再作成しているってことですよね・・chonmage


2009年4月24日金曜日 8:01

回答ありがとうございます。

最初、2万行が問題だと思っていたんですが
対象部分のみのサンプルアプリケーションでは、問題が発生せず
UpdateLayoutに関しても、60msほどで応答が返ってきます

なので、原因がわからなくて・・・


2009年4月24日金曜日 8:12

具体的に何をやられているかは、良く分からないのですが、サンプルアプリも2万行なのですか?

単純に、
2つの文字列変数を持つクラス・・・A
AをコレクションするArrayList
ArrayListに2万行作成・・・5文字程度設定したAをつっこむ
ArrayList を ItemSource に入れる。
これだけでも、すんごい時間かかります。

CLRプロファイラでみると、元の配列に対して、ListView側のオブジェクトがべらぼうにでかく、ネストも多いので、行数のせいかなぁ、なんておもったのですが・・・chonmage


2009年4月24日金曜日 8:35

具体的には、CSVファイルから読み込んだ履歴データを表示する処理を行っております。
子画面のため表示部分は同じ物を使用しており、
サンプルアプリも同じCSVファイルを読み込んでいます。

ListViewのItemSourceには以下のコレクションを使用しています。
標準のソートで7秒かかっていたのでIComparerを実装してます。
ObservableCollection<データクラス名> itemSource;

サンプルと実際のアプリでの処理時間(ミリ秒)は以下になります。

CSV読込み処理
サンプル:1047
実アプリ:1047

ItemSource.Add処理
サンプル:719
実アプリ:766

ItemSource.Sort処理
サンプル:406
実アプリ:422

ListView.UpdateLayout処理
サンプル:78
実アプリ:48031


2009年4月24日金曜日 9:03

ふむぅ、だんだんとDEEPな話になってきてますね。
どちらも、データもソートの実装も同じで、レイアウトの変更で遅くなる部分だけが違うとなると、思いつくのは、UIの構造が、サンプルと、本物では、違うために、1行分のレイアウト変更の都度、XAML特有のメッセージというかイベント?がばかすかやりとりされているのではないだろうか・・・(妄想かもしれません)
サンプルは単純、本物は複雑、なので、XAML特有のイベントループ(って言うのでしたっけ)が何か問題に・・・
なにかそのあたりを探ると良い気がしてきました。

これ以上は、能力の限界を超えそうです(もうしわけない) orz

chonmage


2009年4月24日金曜日 9:09

サンプルと実アプリでどう違うのか分からないのでコメントしづらいですが。
ListView 周りの DataTemplate とかが複雑化している、とか?

// どのみち万単位じゃ一覧性も何も無いので私ならページング機構を追加して一度に表示するのは数百件程度にするかな。。


2009年4月24日金曜日 9:19

ListViewに対して、VirtualizingStackPanel.IsVirtualizing添付プロパティをtrueと指定したらいかがでしょう。


2009年4月24日金曜日 9:23

回答ありがとうございます。

すでにVirtualizingStackPanel.IsVirtualizingはtrueで設定しております。


2009年4月24日金曜日 9:37

回答ありがとうございます。

サンプルと実アプリとの違いは、

実アプリから問題となるListViewの子画面のみを移植した物になります。
その際にListViewの表示に関係ない、
コンパイルエラーになる共通関数部分はコメントアウトしております。

DataTemplateは使用しておりません。

確かに2万行の表示は大きいと思いますが、客先仕様のため変更が出来ない状況です・・・


2009年4月26日日曜日 1:45

リストビューのスタイルで縦線を引く処理が遅いことが判明しました。

下記の処理で”ContentControl Content”の部分です。

<ScrollContentPresenter.Content>
    <Grid>
      <!-- 縦線ノ挿入 -->
      <ItemsControl Margin="3,0,0,0" ItemsSource="{Binding Path=TemplatedParent.View.Columns, RelativeSource={RelativeSource TemplatedParent}}">
        <ItemsControl.ItemTemplate>
          <DataTemplate>
            <Border Width="{Binding Path=ActualWidth}" BorderThickness="0,0,1,0" BorderBrush="{DynamicResource verticalLineColor}" />
          </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.ItemsPanel>
          <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal" />
          </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
      </ItemsControl>
      <ContentControl Content="{TemplateBinding Content}" />
    </Grid>
</ScrollContentPresenter.Content>

高速な縦線を描画する方法は無いでしょうか?


2009年4月26日日曜日 3:02

縦線といってもBorderですね。
Border自体が遅いということはないと思うので、怪しいのはBorderBrushで使っているDynamicResourceですかね。
先ずは、DynamicResourceをStaticResourceにしてみてはいかがでしょうか?
または、とりあえず固定値("Black"等)にして違いを見てみるといいかと思います。

詳しくは、
http://msdn.microsoft.com/ja-jp/library/bb613559.aspx
を確認してください。


2009年4月26日日曜日 8:09

回答ありがとうございます。

試してみましたが、変化なしです。

今回のことで、もともと2000件の場合縦線が出てないことに気づきました。


2009年4月27日月曜日 0:09 | 1 票

良くわからなくなってきましたが・・・
2万件のデータであっても、それだけで遅くなる原因とは言えないと思います。
以前試した際には、10万件のデータでもストレスを感じたことはありませんでした。
もちろん、表現方法やデータの内容によってはあり得ないことではないとは思いますが、
ちょっと情報が錯綜している気がします。

DataTemplateは使用していないと書いてあったのに使っていたり、
縦線の描画が遅いと書いてあったのに描画されていなかったり・・・
混乱されているのかもしれませんが、今一度ボトルネックをはっきりさせたほうがいいかと思います。
同じようなことをしていてパフォーマンスに問題のないアプリがすでにあるのであれば、
少しずつどちらかに近づけていって様子を見たほうが早い気がします。

あと、ちょっと前の話題になりますが、そもそも IsVirtualizing=true でUpdateLayout にそれだけ時間がかかるのがおかしい気がします。見えているのは、何行何列くらいでしょうか?
もしかしたら、仮想化が無効になっているのかもしれません。
http://msdn.microsoft.com/ja-jp/library/cc716879.aspx
にありますが、IsVirtualizing=true にしたからといって、必ず仮想化できるようではないようです。
Snoop(http://blois.us/Snoop/)等で実際どうなっているかを見てみるのもいいと思います。


2009年4月27日月曜日 3:02

VirtualizingStackPanel.IsVirtualizing をtrueにしても、VirtualizingStackPanelを使用していないんじゃ意味無いですね。

ItemsPanelTemplateに設定してあるパネルが、StackPanel ですから。
このStackPanel をVirtualizingStackPanelにするとどうなりますか ?
Sorry, I am not good at English.


2009年4月27日月曜日 5:59

良くわからなくなってきましたが・・・
2万件のデータであっても、それだけで遅くなる原因とは言えないと思います。
以前試した際には、10万件のデータでもストレスを感じたことはありませんでした。
もちろん、表現方法やデータの内容によってはあり得ないことではないとは思いますが、
ちょっと情報が錯綜している気がします。

DataTemplateは使用していないと書いてあったのに使っていたり、
縦線の描画が遅いと書いてあったのに描画されていなかったり・・・
混乱されているのかもしれませんが、今一度ボトルネックをはっきりさせたほうがいいかと思います。
同じようなことをしていてパフォーマンスに問題のないアプリがすでにあるのであれば、
少しずつどちらかに近づけていって様子を見たほうが早い気がします。

あと、ちょっと前の話題になりますが、そもそも IsVirtualizing=true でUpdateLayout にそれだけ時間がかかるのがおかしい気がします。見えているのは、何行何列くらいでしょうか?
もしかしたら、仮想化が無効になっているのかもしれません。
http://msdn.microsoft.com/ja-jp/library/cc716879.aspx
にありますが、IsVirtualizing=true にしたからといって、必ず仮想化できるようではないようです。
Snoop(http://blois.us/Snoop/)等で実際どうなっているかを見てみるのもいいと思います。

回答ありがとうございます。

そうですね、WPFの開発が初めてなのと、ホームページなどのソースコードを参考にしているため、情報が錯綜しています・・・

縦線の描画処理はそのままで、同じソースコードで1000件だと表示され、20000件だと消えます。
同じようなことをして問題のないソースコードを探してみます。

Snoopをインストールして、確認しましたがIsVirtualizing=trueのようです。


2009年4月27日月曜日 6:09

VirtualizingStackPanel.IsVirtualizing をtrueにしても、VirtualizingStackPanelを使用していないんじゃ意味無いですね。

ItemsPanelTemplateに設定してあるパネルが、StackPanel ですから。
このStackPanel をVirtualizingStackPanelにするとどうなりますか ?
Sorry, I am not good at English.

回答ありがとうございます。

StackPanelをVirtualizingStackPanelに変更してみましたが、状況は変わりませんでした。


2009年4月28日火曜日 2:18

ちょっと整理しましょう。

実アプリとサンプルアプリの実行速度、ソート処理後の描画で遅い。という状況は今もかわらないか?
実アプリに加えた変更を、都度サンプルアプリにも変更を行い確認する事が必要ではないか。(原因が判るまで)

データテンプレートは無しにする。
テンプレートを無しにする。
ソート処理自体も無し。

など、いったん今のコードを、最初の状況(速度の問題が起きたコード)より更にシンプルなコード(コメントアウトできるならそうして)にして、分析を行う事をしてみたらどうでしょうか。
そしてその場合、ListViewの見た目に関するXAMLやコードは全て無いものとして、データの表示のみにまず的を絞ってみてはどうでしょうか。
つまり、問題の発生箇所を局所化してコントロールしていくというアプローチです。
そして、徐々に見た目に関するコードを加えていってはどうでしょうか。
この時、実行速度担保の取れている、ソート処理は、最後に組み込むようにします。

chonmage


2009年4月28日火曜日 5:57

そうですね

現状シンプルなソースにして動作させてみました。
・ループにて20000件追加処理を行う
・UpdateLayoutを行う

違いはXAMLのみで、縦線を引くスタイルを使用の有無のみで
以下の結果になりました。(ミリ秒)
問題なし:78
問題あり:48313

スタイルの方法をもう少し調べてみます。 


2009年5月6日水曜日 8:53

最後の書き込みから一週間以上あいてるので解決されてるかもしれませんが
ちょっと手元でも再現させてみて何かいい方法が無いか確認してみたいと思います。

ただ、定時して頂いたコードだと断片的過ぎて性能劣化を引き起こすまでに至りませんでした。
お手数をおかけしますが、現象の再現に必要な情報をもうちょっと頂けないでしょうか。

かずき Blog:http://blogs.wankuma.com/kazuki/


2009年5月7日木曜日 2:53

ありがとうございます。
まだ、解決法を模索しております。
主要なソースを提示いたします。

XAML側のリソースは以下になります。

    <Window.Resources>
        <SolidColorBrush x:Key="verticalLineColor" Color="{DynamicResource {x:Static SystemColors.GradientInactiveCaptionColorKey}}"/>
        <SolidColorBrush x:Key="ListBorder" Color="#828790"/>

        <Style x:Key="{x:Static GridView.GridViewScrollViewerStyleKey}" TargetType="{x:Type ScrollViewer}">
            <Setter Property="Focusable" Value="false"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ScrollViewer}">
                        <Grid SnapsToDevicePixels="true" Background="{TemplateBinding Background}">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="Auto"/>
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="*"/>
                                <RowDefinition Height="Auto"/>
                            </Grid.RowDefinitions>
                            <DockPanel Margin="{TemplateBinding Padding}">
                                <ScrollViewer Focusable="false" DockPanel.Dock="Top" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">
                                    <GridViewHeaderRowPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" AllowsColumnReorder="{Binding Path=TemplatedParent.View.AllowsColumnReorder, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderContainerStyle="{Binding Path=TemplatedParent.View.ColumnHeaderContainerStyle, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderContextMenu="{Binding Path=TemplatedParent.View.ColumnHeaderContextMenu, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderTemplate="{Binding Path=TemplatedParent.View.ColumnHeaderTemplate, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderTemplateSelector="{Binding Path=TemplatedParent.View.ColumnHeaderTemplateSelector, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderToolTip="{Binding Path=TemplatedParent.View.ColumnHeaderToolTip, RelativeSource={RelativeSource TemplatedParent}}" Columns="{Binding Path=TemplatedParent.View.Columns, RelativeSource={RelativeSource TemplatedParent}}"/>
                                </ScrollViewer>
                                <ScrollContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="PART_ScrollContentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" CanContentScroll="{TemplateBinding CanContentScroll}" KeyboardNavigation.DirectionalNavigation="Local">
                                    <!-- <ScrollContentPresenter.Content>を書き換え -->
                                    <ScrollContentPresenter.Content>
                                        <Grid>
                                            <!-- 縦線の挿入 -->
                                            <ItemsControl Margin="3,0,0,0" ItemsSource="{Binding Path=TemplatedParent.View.Columns, RelativeSource={RelativeSource TemplatedParent}}">
                                                <ItemsControl.ItemTemplate>
                                                    <DataTemplate>
                                                        <Border Width="{Binding Path=ActualWidth}" BorderThickness="0,0,1,0" BorderBrush="{DynamicResource verticalLineColor}" />
                                                    </DataTemplate>
                                                </ItemsControl.ItemTemplate>
                                                <ItemsControl.ItemsPanel>
                                                    <ItemsPanelTemplate>
                                                        <StackPanel Orientation="Horizontal" />
                                                    </ItemsPanelTemplate>
                                                </ItemsControl.ItemsPanel>
                                            </ItemsControl>
                                            <ContentControl Content="{TemplateBinding Content}" />
                                        </Grid>
                                    </ScrollContentPresenter.Content>
                                </ScrollContentPresenter>
                            </DockPanel>
                            <ScrollBar Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Cursor="Arrow" x:Name="PART_HorizontalScrollBar" Grid.Row="1" Orientation="Horizontal" ViewportSize="{TemplateBinding ViewportWidth}" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0.0" Value="{Binding Path=HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"/>
                            <ScrollBar Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Cursor="Arrow" x:Name="PART_VerticalScrollBar" Grid.Column="1" Orientation="Vertical" ViewportSize="{TemplateBinding ViewportHeight}" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0.0" Value="{Binding Path=VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"/>
                            <DockPanel Grid.Column="1" Grid.Row="1" Background="{Binding Path=Background, ElementName=PART_VerticalScrollBar}" LastChildFill="false">
                                <Rectangle Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Width="1" Fill="White" DockPanel.Dock="Left"/>
                                <Rectangle Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Height="1" Fill="White" DockPanel.Dock="Top"/>
                            </DockPanel>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <Style x:Key="CustomListViewStyle" TargetType="{x:Type ListView}">
            <Setter Property="FontSize" Value="14"/>
            <Setter Property="FontFamily" Value="MS Gothic"/>
            <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
            <Setter Property="BorderBrush" Value="{x:Static Microsoft_Windows_Themes:ClassicBorderDecorator.ClassicBorderBrush}"/>
            <Setter Property="BorderThickness" Value="2"/>
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
            <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
            <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
            <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListView}">
                        <Microsoft_Windows_Themes:ClassicBorderDecorator SnapsToDevicePixels="true" x:Name="Bd" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderStyle="Sunken" BorderThickness="{TemplateBinding BorderThickness}">
                            <ScrollViewer Padding="{TemplateBinding Padding}" Style="{DynamicResource {x:Static GridView.GridViewScrollViewerStyleKey}}">
                                <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                            </ScrollViewer>
                        </Microsoft_Windows_Themes:ClassicBorderDecorator>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsGrouping" Value="true">
                                <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
                            </Trigger>
                            <Trigger Property="IsEnabled" Value="false">
                                <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>

C#ソース側は以下になります。
ListShowDataはリストビューのBindingしているstring型のデータクラスになります。

                System.Diagnostics.Debug.WriteLine("listview.Items.Add Start [" + Environment.TickCount + "]");
                for(i = 0; i < 20000; i++)
                {
                    listshowdata = new ListShowData(
                        "データ1_" + i.ToString("D5"),
                        "データ2_" + i.ToString("D5"),
                        "データ3_" + i.ToString("D5"),
                        "データ4_" + i.ToString("D5")
                        );
                    listview.Items.Add(listshowdata);
                }
                System.Diagnostics.Debug.WriteLine("listview.Items.Add End [" + Environment.TickCount + "]");

                System.Diagnostics.Debug.WriteLine("UpdateLayout Start [" + Environment.TickCount + "]");
                listview.UpdateLayout();
                System.Diagnostics.Debug.WriteLine("UpdateLayout End [" + Environment.TickCount + "]");

よろしくお願いいたします。


2009年5月7日木曜日 13:01 | 1 票

試してみた感じだと、1レコード単位でBorderを作ってる部分の有無で処理時間が大きく変わってしまいますね。
縦線だけなら、1レコード単位で作らなくても、全体で1つ作ってやればいいんじゃないかと思いGridViewScrollViewerStyleKeyを下のようにしてみましたが…
横スクロールがあるときに一番右までスクロールバーを移動させると少しずれてしまいますorz

<Style x:Key="{x:Static GridView.GridViewScrollViewerStyleKey}" TargetType="{x:Type ScrollViewer}">

    <Setter Property="Focusable" Value="false"/>

    <Setter Property="Template">

        <Setter.Value>

            <ControlTemplate TargetType="{x:Type ScrollViewer}">

                <Grid SnapsToDevicePixels="true" Background="{TemplateBinding Background}">

                    <Grid.ColumnDefinitions>

                        <ColumnDefinition Width="*"/>

                        <ColumnDefinition Width="Auto"/>

                    </Grid.ColumnDefinitions>

                    <Grid.RowDefinitions>

                        <RowDefinition Height="*"/>

                        <RowDefinition Height="Auto"/>

                    </Grid.RowDefinitions>

                    <DockPanel Margin="{TemplateBinding Padding}">

                        <ScrollViewer Focusable="false" DockPanel.Dock="Top" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">

                            <GridViewHeaderRowPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" ScrollViewer.ScrollChanged="header_ScrollChanged"

                                                        Name="header"

                                                        AllowsColumnReorder="{Binding Path=TemplatedParent.View.AllowsColumnReorder, RelativeSource={RelativeSource TemplatedParent}}" 

                                                        ColumnHeaderContainerStyle="{Binding Path=TemplatedParent.View.ColumnHeaderContainerStyle, RelativeSource={RelativeSource TemplatedParent}}" 

                                                        ColumnHeaderContextMenu="{Binding Path=TemplatedParent.View.ColumnHeaderContextMenu, RelativeSource={RelativeSource TemplatedParent}}" 

                                                        ColumnHeaderTemplate="{Binding Path=TemplatedParent.View.ColumnHeaderTemplate, RelativeSource={RelativeSource TemplatedParent}}" 

                                                        ColumnHeaderTemplateSelector="{Binding Path=TemplatedParent.View.ColumnHeaderTemplateSelector, RelativeSource={RelativeSource TemplatedParent}}" 

                                                        ColumnHeaderToolTip="{Binding Path=TemplatedParent.View.ColumnHeaderToolTip, RelativeSource={RelativeSource TemplatedParent}}" 

                                                        Columns="{Binding Path=TemplatedParent.View.Columns, RelativeSource={RelativeSource TemplatedParent}}"

                                                        />

                        </ScrollViewer>

                        <Grid HorizontalAlignment="Stretch" Margin="0,0,3,0">

                            <ScrollContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="PART_ScrollContentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" CanContentScroll="{TemplateBinding CanContentScroll}" KeyboardNavigation.DirectionalNavigation="Local" />

                            <!-- 縦線の挿入 -->

                            <Canvas>

                                <ItemsControl Canvas.Left="{Binding HorizontalOffset, Mode=OneWay, Converter={StaticResource negativeConverter}, RelativeSource={RelativeSource TemplatedParent}}"

                                              IsHitTestVisible="False"

                                              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"

                                              ItemsSource="{Binding Path=TemplatedParent.View.Columns, RelativeSource={RelativeSource TemplatedParent}}"

                                              Height="{TemplateBinding ActualHeight}"

                                              Width="{Binding ElementName=header, Path=ActualWidth}">

                                    <ItemsControl.ItemTemplate>

                                        <DataTemplate>

                                            <Border Width="{Binding Path=ActualWidth}" BorderThickness="1,0,1,0" BorderBrush="{DynamicResource verticalLineColor}" />

                                        </DataTemplate>

                                    </ItemsControl.ItemTemplate>

                                    <ItemsControl.ItemsPanel>

                                        <ItemsPanelTemplate>

                                            <StackPanel Orientation="Horizontal" />

                                        </ItemsPanelTemplate>

                                    </ItemsControl.ItemsPanel>

                                </ItemsControl>

                            </Canvas>

                        </Grid>

                    </DockPanel>

                    <ScrollBar Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Cursor="Arrow" x:Name="PART_HorizontalScrollBar" Grid.Row="1" Orientation="Horizontal" ViewportSize="{TemplateBinding ViewportWidth}" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0.0" Value="{Binding Path=HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"/>

                    <ScrollBar Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Cursor="Arrow" x:Name="PART_VerticalScrollBar" Grid.Column="1" Orientation="Vertical" ViewportSize="{TemplateBinding ViewportHeight}" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0.0" Value="{Binding Path=VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"/>

                    <DockPanel Grid.Column="1" Grid.Row="1" Background="{Binding Path=Background, ElementName=PART_VerticalScrollBar}" LastChildFill="false">

                        <Rectangle Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Width="1" Fill="White" DockPanel.Dock="Left"/>

                        <Rectangle Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Height="1" Fill="White" DockPanel.Dock="Top"/>

                    </DockPanel>

                </Grid>

            </ControlTemplate>

        </Setter.Value>

    </Setter>

</Style>

上のものを動かすにはnegativeConverterという名前で以下のクラスをWindowのResourcesに追加する必要もあります。

    public class NegativeConverter : IValueConverter

    {

        #region IValueConverter メンバ



        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

        {

            double val = (double)value;

            Debug.WriteLine("conv: " + val);

            return -val;

        }



        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

        {

            throw new NotImplementedException();

        }



        #endregion

    }

かずき Blog:http://blogs.wankuma.com/kazuki/


2009年5月8日金曜日 1:01

ありがとうございます。
高速に表示できるようになったのですが、縦の線がヘッダのサイズ分ListViewを越えて下に表示されてしまいます。
縦線がListViewに収まるようにするにはどのようにすればよいのでしょうか?


2009年5月8日金曜日 10:33

a_かずき_さん、ありがとうございました。
無事表示することが出来ました。

これまで、回答していただいた方々も
本当にありがとうございました。


2009年5月8日金曜日 23:52

横スクロールバーが表示されたときに一番右端までスクロールすると
ちょっとずれてしまうんですけど、そこらへんは許容できる範囲でしょうか^^;かずき Blog:http://blogs.wankuma.com/kazuki/


2009年5月9日土曜日 0:11

はい、横スクロール非対応のため大丈夫です。

かずきさんのホームページの
「[WPF][C#]ListViewのGridViewに罫線を引きたい」を参考に横線の処理も使わせていただきました。