<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_Life Is Art</title><subtitle type="text">We Design</subtitle><id>http://feed.cnblogs.com/blog/u/39435/rss</id><updated>2011-04-12T02:58:42Z</updated><author><name>RMay</name><uri>http://www.cnblogs.com/RMay/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/RMay/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/39435/rss"/><entry><id>http://www.cnblogs.com/RMay/archive/2011/04/03/2004216.html</id><title type="text">【WPF】自定义金额输入控件CurrencyEditor和限制输入控件FieldTextBox</title><summary type="text">原来没有考虑到+/-输入的情况，已修改由于项目的需要，我们在某些场合下需要对输入做限制，例如金额，需要靠右对齐，需要显示货币符号，需要显示分隔符号等等。相信大家都碰到过这种需求。上网找这种控件也很难找，要么就是收费的，要么就是不太符合国人的习惯。例如，原来用过一个第三方NetAdvantage控件，但是它是严格按照货币的格式化方式来格式化的，不适合国人的金额格式习惯。因为国人的金额格式习惯是类似于 $#,###,###.##，但是某些币种，小数点是','，分组符号是'.'，是反过来的，很容易让人看错；而某些币种的输入方式是从右往左，就更不适应了。因此，自己写了一</summary><published>2011-04-03T01:46:00Z</published><updated>2011-04-03T01:46:00Z</updated><author><name>RMay</name><uri>http://www.cnblogs.com/RMay/</uri></author><link rel="alternate" href="http://www.cnblogs.com/RMay/archive/2011/04/03/2004216.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/RMay/archive/2011/04/03/2004216.html"/><content type="html">&lt;p&gt;原来没有考虑到+/-输入的情况，已修改&lt;/p&gt;&lt;p&gt;由于项目的需要，我们在某些场合下需要对输入做限制，例如金额，需要靠右对齐，需要显示货币符号，需要显示分隔符号等等。相信大家都碰到过这种需求。上网找这种控件也很难找，要么就是收费的，要么就是不太符合国人的习惯。例如，原来用过一个第三方NetAdvantage控件，但是它是严格按照货币的格式化方式来格式化的，不适合国人的金额格式习惯。因为国人的金额格式习惯是类似于 $#,###,###.##，但是某些币种，小数点是','，分组符号是'.'，是反过来的，很容易让人看错；而某些币种的输入方式是从右往左，就更不适应了。&lt;/p&gt;&lt;p&gt;因此，自己写了一个金额输入控件CurrencyEditor，可以根据不同的语言显示不同的货币符号和限制小数位数。没有直接用.Net的格式化decimal，而是自己调用.Net格式化之后，再处理为&amp;ldquo;货币符号+金额值&amp;rdquo;的形式。&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/35870/2011040309460195.png" /&gt;&lt;/p&gt;&lt;p&gt;CurrencyEditor继承自TextBox，要点是在OnTextChanged中去解析文本是否合法，并且将文本格式化，然后设置光标的位置。其实TextBox还有一个TextInput事件，但是在这个事件中处理的问题在于，复制粘贴操作不会触发TextInput，会导致用户可以用复制粘贴的方式录入非法文本。其次，就是在OnSelectionChanged中去检查光标的位置，要保证用户录入的舒适性。在OnPreviewKeyDown中处理一些非法录入，和控制光标位置，例如按下'.'直接跳到小数点之后，同时控制用户通过DEL和Backspace不会去删除掉货币符号和小数点。详情还是见代码吧，注释很详尽。&lt;/p&gt;&lt;p&gt;另外一个控件是限制输入的FieldTextBox，限制有两方面，一个是输入的内容，有Text和Digit两种。Text可以任意输入，Digit只能输入数字（例如，在输入卡号的时候很有用）。另一个是限制输入的字节长度，这个限制在输入一个报文中，按照字节有长度限制的字段时很有用。WPF的TextBox虽然有一个MaxLength，但是限制的是字符长度。例如，&amp;ldquo;我&amp;rdquo;是两个字节，却只是一个字符。FieldTextBox的处理逻辑与CurrencyEditor类似，但是要稍微简单一点。&lt;/p&gt;&lt;p&gt;附代码，跟大家分享一下:)&lt;/p&gt;&lt;p&gt;&lt;a href="http://files.cnblogs.com/RMay/WpfInputs.zip"&gt;http://files.cnblogs.com/RMay/WpfInputs.zip&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/RMay/aggbug/2004216.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/RMay/archive/2011/04/03/2004216.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/RMay/archive/2010/12/27/1918048.html</id><title type="text">【WPF】自定义GridLineDecorator给ListView画网格</title><summary type="text">不改动现有ListView的情况下，使用自定义GridLineDecorator，给ListView轻松增加画网格线的功能</summary><published>2010-12-27T08:59:00Z</published><updated>2010-12-27T08:59:00Z</updated><author><name>RMay</name><uri>http://www.cnblogs.com/RMay/</uri></author><link rel="alternate" href="http://www.cnblogs.com/RMay/archive/2010/12/27/1918048.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/RMay/archive/2010/12/27/1918048.html"/><content type="html">&lt;p&gt;&lt;span style="color: #ff0000;"&gt;感谢&amp;nbsp;&lt;/span&gt;&lt;a id="Comments1_CommentList_ctl02_NameLink" href="http://www.cnblogs.com/rgqancy/" target="_blank"&gt;rgqancy&lt;/a&gt;&amp;nbsp;&lt;span style="color: #ff0000;"&gt;指出的Bug，已经修正&lt;/span&gt;&lt;/p&gt;&lt;p&gt;先给个效果图：&lt;/p&gt;&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/35870/2010122716310865.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;使用时的代码：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('d838208f-60c3-478f-a2bd-e2466accc93a')"&gt;&lt;div id="cnblogs_code_open_d838208f-60c3-478f-a2bd-e2466accc93a"&gt;&lt;div&gt;&lt;!--&lt;br /&gt;&lt;br /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br /&gt;http://www.CodeHighlighter.com/&lt;br /&gt;&lt;br /&gt;--&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;l:GridLineDecorator&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;ListView &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;ItemsSource&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="&lt;/span&gt;&lt;span style="color: #808000;"&gt;{Binding}&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;ListView.View&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;GridView&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;GridViewColumn &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Header&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Id"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; DisplayMemberBinding&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="&lt;/span&gt;&lt;span style="color: #808000;"&gt;{Binding Id}&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;GridViewColumn &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Header&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Name"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; DisplayMemberBinding&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="&lt;/span&gt;&lt;span style="color: #808000;"&gt;{Binding Name}&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;GridView&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;ListView.View&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;ListView&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;l:GridLineDecorator&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;------------------------正文-------------------------------&lt;/p&gt;&lt;div&gt;&lt;span class="Apple"&gt;&lt;span class="Apple"&gt;&lt;p&gt;经常看见有人问在使用WPF的ListView的时候，怎样能够有网格线的效果。例如&lt;a href="http://www.bbniu.com/forum/thread-1090-1-1.html"&gt;http://www.bbniu.com/forum/thread-1090-1-1.html&lt;/a&gt;&lt;/p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;对这个问题，首先能想到的解决办法是，在GridViewColumn的CellTemplate中，放上一个Border，然后设置Border的BorderBrush和BorderThickness。例如：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" style="overflow-x: auto; overflow-y: auto; background-color: #f5f5f5; width: 700px; font-family: 'Courier New'; font-size: 13px; word-break: break-all; border: #cccccc 1px solid; padding: 5px;"&gt;&lt;div&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;GridViewColumn.CellTemplate&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;DataTemplate&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Border &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;BorderBrush&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="LightGray"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; BorderThickness&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="1"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; UseLayoutRounding&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="True"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;TextBlock &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Text&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="&lt;/span&gt;&lt;span style="color: #808000;"&gt;{Binding Id}&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;Border&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;DataTemplate&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;GridViewColumn.CellTemplate&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;但是，很快你会发现，Border不能随着列宽的变化而变化，就像这样：&lt;/p&gt;&lt;p&gt;&lt;img style="border-width: 0px;" src="http://pic002.cnblogs.com/images/2010/35870/2010122716004992.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;而且，即使将ListView的HorizontalContentAlignment置为Stretch，也不能起到作用。必须在ListViewItem上设置HorizontalContentAlignment="True"。因此，必须添加一个ListViewItem的样式，统一指定：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" style="overflow-x: auto; overflow-y: auto; background-color: #f5f5f5; width: 700px; font-family: 'Courier New'; font-size: 13px; word-break: break-all; border: #cccccc 1px solid; padding: 5px;"&gt;&lt;div&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Style &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;TargetType&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="ListViewItem"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000;"&gt;Setter &lt;/span&gt;&lt;span style="color: #ff0000;"&gt;Property&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="HorizontalContentAlignment"&lt;/span&gt;&lt;span style="color: #ff0000;"&gt; Value&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;="Stretch"&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000;"&gt;Style&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;但问题还是没有解决，因为Border不能填满整个Cell，就像这样：&lt;/p&gt;&lt;p&gt;&lt;img style="border-width: 0px;" src="http://pic002.cnblogs.com/images/2010/35870/2010122716044035.png" alt="" /&gt;&lt;/p&gt;&lt;p&gt;于是，你得小心的设置各个Border的Margin，来让它们&amp;ldquo;恰好&amp;rdquo;都连在一起，看上去就像是连续的线条。也许调整Margin还不够，还得修改ListViewItem的模板；模板修改好了，发现创建这么多的Border性能又跟不上；最头大的是，每个Column都要指定一次CellTemplate，万一哪天边线的颜色要统一调整一下&amp;hellip;&amp;hellip;&lt;/p&gt;&lt;p&gt;因此，这种办法固然可行，操作起来其实麻烦的要死。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;有没有一种方式，可以直接在ListView上&amp;ldquo;画线&amp;rdquo;呢？固然，我们可以自己写一个ListView，在OnRender里面画线什么的，但理想的情况还是能够在可以不改动任何现有控件的条件下，实现这个画网格的功能。同时，这个网格线的颜色可以随意调整就更好了。&lt;/p&gt;&lt;p&gt;因此，总的要求如下：&lt;/p&gt;&lt;p&gt;1、可以画网格&lt;/p&gt;&lt;p&gt;2、不用改动ListView，或者自己写ListView&lt;/p&gt;&lt;p&gt;3、可以调整网格的颜色&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;如果对设计模式熟悉的话，&amp;ldquo;不改动现有代码，增加新的功能&amp;rdquo;，应该马上能够想到装饰器模式。其实，WPF中本身就有Decorator这个控件，而常用的Border就是一个Decorator，可以帮助控件画背景色，画边线等等。&lt;/p&gt;&lt;p&gt;因此，如果能够有这么一个Decorator，把ListView往里面一放，就能有画线的功能，岂不快哉？不过，这里我并不打算直接继承Decorator来修改，因为WPF提供的Decorator是针对所有UIElment的，而我们只想针对ListView。&lt;/p&gt;&lt;p&gt;GridLineDecorator直接继承自FrameworkElement，并且通过重载VisualChild和LogicalChild相关的代码来显示其包装的ListView。&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span class="Apple" style="widows: 2; text-transform: none; text-indent: 0px; border-collapse: separate; font: medium Simsun; white-space: normal; orphans: 2; letter-spacing: normal; color: #000000; word-spacing: 0px;"&gt;&lt;span class="Apple" style="line-height: 21px; font-family: verdana, 'courier new'; font-size: 14px;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('3605217b-a861-4561-b820-769f70f644c8')"&gt;&lt;div id="cnblogs_code_open_3605217b-a861-4561-b820-769f70f644c8" class="cnblogs_code_hide"&gt;&lt;div&gt;&lt;!--&lt;br /&gt;&lt;br /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br /&gt;http://www.CodeHighlighter.com/&lt;br /&gt;&lt;br /&gt;--&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System.Collections.Generic;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System.Linq;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System.Text;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System.Windows;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System.Windows.Controls;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System.Windows.Markup;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System.Windows.Media;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; System.Windows.Threading;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;namespace&lt;/span&gt;&lt;span style="color: #000000;"&gt; ListViewWithLines&lt;br /&gt;{&lt;br /&gt;    [ContentProperty(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Target&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]&lt;br /&gt;    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; GridLineDecorator : FrameworkElement&lt;br /&gt;    {&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; ListView _target;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; DrawingVisual _gridLinesVisual &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; DrawingVisual();&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; GridViewHeaderRowPresenter _headerRowPresenter &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; GridLineDecorator()&lt;br /&gt;        {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.AddVisualChild(_gridLinesVisual);&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.AddHandler(ScrollViewer.ScrollChangedEvent, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; RoutedEventHandler(OnScrollChanged));&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#region&lt;/span&gt;&lt;span style="color: #000000;"&gt; GridLineBrush&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; GridLineBrush Dependency Property&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;readonly&lt;/span&gt;&lt;span style="color: #000000;"&gt; DependencyProperty GridLineBrushProperty &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;            DependencyProperty.Register(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;GridLineBrush&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt;&lt;span style="color: #000000;"&gt;(Brush), &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;typeof&lt;/span&gt;&lt;span style="color: #000000;"&gt;(GridLineDecorator),&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; FrameworkPropertyMetadata(Brushes.LightGray,&lt;br /&gt;                    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; PropertyChangedCallback(OnGridLineBrushChanged)));&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; Gets or sets the GridLineBrush property.  This dependency property &lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; indicates ....&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; Brush GridLineBrush&lt;br /&gt;        {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt; { &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; (Brush)GetValue(GridLineBrushProperty); }&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt; { SetValue(GridLineBrushProperty, value); }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; Handles changes to the GridLineBrush property.&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;static&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; OnGridLineBrushChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            ((GridLineDecorator)d).OnGridLineBrushChanged(e);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; Provides derived classes an opportunity to handle changes to the GridLineBrush property.&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #808080;"&gt;///&lt;/span&gt;&lt;span style="color: #008000;"&gt; &lt;/span&gt;&lt;span style="color: #808080;"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span style="color: #808080;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;protected&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;virtual&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; OnGridLineBrushChanged(DependencyPropertyChangedEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            DrawGridLines();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#endregion&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#region&lt;/span&gt;&lt;span style="color: #000000;"&gt; Target&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; ListView Target&lt;br /&gt;        {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt; { &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; _target; }&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;set&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;            {&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (_target &lt;/span&gt;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&lt;span style="color: #000000;"&gt; value)&lt;br /&gt;                {&lt;br /&gt;                    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (_target &lt;/span&gt;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;) Detach();&lt;br /&gt;                    RemoveVisualChild(_target);&lt;br /&gt;                    RemoveLogicalChild(_target);&lt;br /&gt;&lt;br /&gt;                    _target &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; value;&lt;br /&gt;&lt;br /&gt;                    AddVisualChild(_target);&lt;br /&gt;                    AddLogicalChild(_target);&lt;br /&gt;                    &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (_target &lt;/span&gt;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;) Attach();&lt;br /&gt;&lt;br /&gt;                    InvalidateMeasure();&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; GetGridViewHeaderPresenter()&lt;br /&gt;        {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (Target &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;            {&lt;br /&gt;                _headerRowPresenter &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;            }&lt;br /&gt;            _headerRowPresenter &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; Target.GetDesendentChild&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;GridViewHeaderRowPresenter&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#endregion&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#region&lt;/span&gt;&lt;span style="color: #000000;"&gt; DrawGridLines&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; DrawGridLines()&lt;br /&gt;        {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (Target &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;) &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (_headerRowPresenter &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;) &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;br /&gt;            var itemCount &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; Target.Items.Count;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (itemCount &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;) &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;br /&gt;            var gridView &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; Target.View &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;as&lt;/span&gt;&lt;span style="color: #000000;"&gt; GridView;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (gridView &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;) &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;            &lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 获取drawingContext&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;            var drawingContext &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; _gridLinesVisual.RenderOpen();&lt;br /&gt;            var startPoint &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; Point(&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;            var totalHeight &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0.0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 为了对齐到像素的计算参数，否则就会看到有些线是模糊的&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;            var dpiFactor &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.GetDpiFactor();&lt;br /&gt;            var pen &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; Pen(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.GridLineBrush, &lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;*&lt;/span&gt;&lt;span style="color: #000000;"&gt; dpiFactor);&lt;br /&gt;            var halfPenWidth &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; pen.Thickness &lt;/span&gt;&lt;span style="color: #000000;"&gt;/&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;2&lt;/span&gt;&lt;span style="color: #000000;"&gt;;&lt;br /&gt;            var guidelines &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; GuidelineSet();&lt;br /&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 画横线&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;for&lt;/span&gt;&lt;span style="color: #000000;"&gt; (&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; i &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;; i &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000;"&gt; itemCount; i&lt;/span&gt;&lt;span style="color: #000000;"&gt;++&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;            {&lt;br /&gt;                var item &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; Target.ItemContainerGenerator.ContainerFromIndex(i) &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;as&lt;/span&gt;&lt;span style="color: #000000;"&gt; ListViewItem;&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (item &lt;/span&gt;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;                {&lt;br /&gt;                    var renderSize &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; item.RenderSize;&lt;br /&gt;                    var offset &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; item.TranslatePoint(startPoint, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&lt;br /&gt;                    var hLineX1 &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; offset.X;&lt;br /&gt;                    var hLineX2 &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; offset.X &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; renderSize.Width;&lt;br /&gt;                    var hLineY &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; offset.Y &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; renderSize.Height;&lt;br /&gt;&lt;br /&gt;                    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 加入参考线，对齐到像素&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;                    guidelines.GuidelinesY.Add(hLineY &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; halfPenWidth);&lt;br /&gt;                    drawingContext.PushGuidelineSet(guidelines);&lt;br /&gt;                    drawingContext.DrawLine(pen, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; Point(hLineX1, hLineY), &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; Point(hLineX2, hLineY));&lt;br /&gt;                    drawingContext.Pop();&lt;br /&gt;&lt;br /&gt;                    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 计算竖线总高度&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;                    totalHeight &lt;/span&gt;&lt;span style="color: #000000;"&gt;+=&lt;/span&gt;&lt;span style="color: #000000;"&gt; renderSize.Height;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 画竖线&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;            var columns &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; gridView.Columns;&lt;br /&gt;            var headerOffset &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; _headerRowPresenter.TranslatePoint(startPoint, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;            var headerSize &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; _headerRowPresenter.RenderSize;&lt;br /&gt;&lt;br /&gt;            var vLineX &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; headerOffset.X;&lt;br /&gt;            var vLineY1 &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; headerOffset.Y &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; headerSize.Height;&lt;br /&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;foreach&lt;/span&gt;&lt;span style="color: #000000;"&gt; (var column &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;in&lt;/span&gt;&lt;span style="color: #000000;"&gt; columns)&lt;br /&gt;            {&lt;br /&gt;                var columnWidth &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; column.GetColumnWidth();&lt;br /&gt;                vLineX &lt;/span&gt;&lt;span style="color: #000000;"&gt;+=&lt;/span&gt;&lt;span style="color: #000000;"&gt; columnWidth;&lt;br /&gt;&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; 加入参考线，对齐到像素&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;                guidelines.GuidelinesX.Add(vLineX &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; halfPenWidth);&lt;br /&gt;                drawingContext.PushGuidelineSet(guidelines);&lt;br /&gt;                drawingContext.DrawLine(pen, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; Point(vLineX, vLineY1), &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; Point(vLineX, totalHeight));&lt;br /&gt;                drawingContext.Pop();&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            drawingContext.Close();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#endregion&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#region&lt;/span&gt;&lt;span style="color: #000000;"&gt; Overrides to show Target and grid lines&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;protected&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;override&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; VisualChildrenCount&lt;br /&gt;        {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt; { &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; Target &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;?&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt; : &lt;/span&gt;&lt;span style="color: #800080;"&gt;2&lt;/span&gt;&lt;span style="color: #000000;"&gt;; }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;protected&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;override&lt;/span&gt;&lt;span style="color: #000000;"&gt; System.Collections.IEnumerator LogicalChildren&lt;br /&gt;        {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;get&lt;/span&gt;&lt;span style="color: #000000;"&gt; { &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;yield&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; Target; }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;protected&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;override&lt;/span&gt;&lt;span style="color: #000000;"&gt; Visual GetVisualChild(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; index)&lt;br /&gt;        {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (index &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;) &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; _target;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (index &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;1&lt;/span&gt;&lt;span style="color: #000000;"&gt;) &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; _gridLinesVisual;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;throw&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; IndexOutOfRangeException(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;.Format(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Index of visual child '{0}' is out of range&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, index));&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;protected&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;override&lt;/span&gt;&lt;span style="color: #000000;"&gt; Size MeasureOverride(Size availableSize)&lt;br /&gt;        {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (Target &lt;/span&gt;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;            {&lt;br /&gt;                Target.Measure(availableSize);&lt;br /&gt;                &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; Target.DesiredSize;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;base&lt;/span&gt;&lt;span style="color: #000000;"&gt;.MeasureOverride(availableSize);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;protected&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;override&lt;/span&gt;&lt;span style="color: #000000;"&gt; Size ArrangeOverride(Size finalSize)&lt;br /&gt;        {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (Target &lt;/span&gt;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;                Target.Arrange(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; Rect(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; Point(&lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;, &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;), finalSize));&lt;br /&gt;&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;return&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;base&lt;/span&gt;&lt;span style="color: #000000;"&gt;.ArrangeOverride(finalSize);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#endregion&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#region&lt;/span&gt;&lt;span style="color: #000000;"&gt; Handle Events&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; Attach()&lt;br /&gt;        {&lt;br /&gt;            _target.Loaded &lt;/span&gt;&lt;span style="color: #000000;"&gt;+=&lt;/span&gt;&lt;span style="color: #000000;"&gt; OnTargetLoaded;&lt;br /&gt;            _target.Unloaded &lt;/span&gt;&lt;span style="color: #000000;"&gt;+=&lt;/span&gt;&lt;span style="color: #000000;"&gt; OnTargetUnloaded;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; Detach()&lt;br /&gt;        {&lt;br /&gt;            _target.Loaded &lt;/span&gt;&lt;span style="color: #000000;"&gt;-=&lt;/span&gt;&lt;span style="color: #000000;"&gt; OnTargetLoaded;&lt;br /&gt;            _target.Unloaded &lt;/span&gt;&lt;span style="color: #000000;"&gt;-=&lt;/span&gt;&lt;span style="color: #000000;"&gt; OnTargetUnloaded;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; OnTargetLoaded(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt; sender, RoutedEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (_headerRowPresenter &lt;/span&gt;&lt;span style="color: #000000;"&gt;==&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;)&lt;br /&gt;                GetGridViewHeaderPresenter();&lt;br /&gt;            DrawGridLines();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; OnTargetUnloaded(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt; sender, RoutedEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            DrawGridLines();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; OnScrollChanged(&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt; sender, RoutedEventArgs e)&lt;br /&gt;        {&lt;br /&gt;            DrawGridLines();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;#endregion&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;    }&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;其中，Target是一个属性，类型是ListView，而有一个_guidLinesVisual，则是用于绘制网格的DrawingVisual。有人可能会问，为什么不直接重载OnRender方法，在里面画线呢？&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;理由是，重载OnRender方法画线，当ListView设置了背景后，会将我们画的线盖住。这是因为控件的背景是在模板中放了一个Border来绘制的，Border也是在OnRender中绘制的，它后绘制，我们的先绘制，会将我们画的线给盖住。同时，你会发现，当ListView的Column改变大小的时候，并不会引起GridLineDecorator重绘，所以网格线无法同步变化。&lt;/p&gt;&lt;p&gt;其实，GridLineDecorator里面的GetVisualChild重载也非常讲究：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('c0ff86d8-3bd1-4265-9d31-f684535374bb')"&gt;&lt;div id="cnblogs_code_open_c0ff86d8-3bd1-4265-9d31-f684535374bb"&gt;&lt;div&gt;&lt;!--&lt;br /&gt;&lt;br /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br /&gt;http://www.CodeHighlighter.com/&lt;br /&gt;&lt;br /&gt;--&gt;&lt;span style="color: #000000;"&gt;        protected override Visual GetVisualChild(int index)&lt;br /&gt;        {&lt;br /&gt;            if (index == 0) return _target;&lt;br /&gt;            if (index == 1) return _gridLinesVisual;&lt;br /&gt;            throw new IndexOutOfRangeException(string.Format("Index of visual child '{0}' is out of range", index));&lt;br /&gt;        }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;首先返回的是ListView，接着才是_gridLinesVisual。&lt;br /&gt;不过，即使是使用DrawingVisual，也会有Column宽度改变无法通知重绘的问题。解决这个问题有好几个思路：&lt;br /&gt;1、监听一下GridViewColumn的宽度变化&lt;br /&gt;2、监听CompositionTarget.Rendering事件&lt;br /&gt;第一个办法，不可行，因为GridViewColumn的宽度变化事件你找不到，第二办法是可行，不过效率嘛&amp;hellip;&amp;hellip;&lt;/p&gt;&lt;p&gt;在经过一番研究之后，终于找到了一个可行的办法，监听ScrollViewer的ScrollChanged事件，因为ListView内部是放置了两个ScrollViewer，一个用于显示Header，一个用于显示Items。当Column的宽度变化时，会触发ScrollViewer的ScrollChanged事件。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;因此，在构造函数里面：&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('76b58736-a0ab-4878-b75b-85855a585ae7')"&gt;&lt;div id="cnblogs_code_open_76b58736-a0ab-4878-b75b-85855a585ae7"&gt;&lt;div&gt;&lt;!--&lt;br /&gt;&lt;br /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br /&gt;http://www.CodeHighlighter.com/&lt;br /&gt;&lt;br /&gt;--&gt;&lt;span style="color: #000000;"&gt;        &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; GridLineDecorator()&lt;br /&gt;        {&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.AddVisualChild(_gridLinesVisual);&lt;br /&gt;            &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;this&lt;/span&gt;&lt;span style="color: #000000;"&gt;.AddHandler(ScrollViewer.ScrollChangedEvent, &lt;/span&gt;&lt;span style="color: #0000ff;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; RoutedEventHandler(OnScrollChanged));&lt;br /&gt;        }&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;画线的逻辑，主要就是遍历所有的Container（其实是ListViewItem），计算其相对于GridLineDecorator的位移，算出横线和纵线的坐标和长度，画线。代码比较多，大家可以下载以后自己看。&lt;/p&gt;&lt;p&gt;细心的童鞋可能会发现，有时候底部的线条在ListViewItem显示不完整时，没有画到最下端，这是由于ListView做了Virtualize处理。大家可以设置VirtualizingStackPanel.IsVirtualizing="False"来强制绘制。&lt;/p&gt;&lt;p&gt;附代码：&lt;a href="http://files.cnblogs.com/RMay/ListViewWithLines.zip"&gt;http://files.cnblogs.com/RMay/ListViewWithLines.zip&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/RMay/aggbug/1918048.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/RMay/archive/2010/12/27/1918048.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/RMay/archive/2010/05/27/1745636.html</id><title type="text">【WPF】WPF 4.0 DatePicker 快速录入</title><summary type="text">先发表在棒棒牛了，转过来吧。传送门：http://www.bbniu.com/forum/viewthread.php?tid=752&amp;page=1&amp;extra=#pid6692WPF 4.0的DatePicker在通过键盘录入日期的时候是非常让人郁闷的。必须按照日期的格式来完整输入例如，比如输入“2010/10/10”才能识别。而实际上在一些要求快速录入的...</summary><published>2010-05-27T09:35:00Z</published><updated>2010-05-27T09:35:00Z</updated><author><name>RMay</name><uri>http://www.cnblogs.com/RMay/</uri></author><link rel="alternate" href="http://www.cnblogs.com/RMay/archive/2010/05/27/1745636.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/RMay/archive/2010/05/27/1745636.html"/><content type="text">先发表在棒棒牛了，转过来吧。传送门：http://www.bbniu.com/forum/viewthread.php?tid=752&amp;page=1&amp;extra=#pid6692WPF 4.0的DatePicker在通过键盘录入日期的时候是非常让人郁闷的。必须按照日期的格式来完整输入例如，比如输入“2010/10/10”才能识别。而实际上在一些要求快速录入的...</content></entry><entry><id>http://www.cnblogs.com/RMay/archive/2010/05/27/1745388.html</id><title type="text">【WPF】监听WPF的WebBrowser控件弹出新窗口的事件</title><summary type="text">WPF中自带一个WebBrowser控件，当我们使用它打开一个网页，例如百度，然后点击它其中的链接时，如果这个链接是会弹出一个新窗口的，那么它会生生的弹出一个IE窗口来，而不是在内部跳到该链接。如果使用Winform的WebBrowser控件，我们可以监听它的NewWindow事件，在这个事件中做一些处理，例如，在新建一个Tab来打开，或者控制它在当前WebBrowser中跳转。很不幸的是，WPF...</summary><published>2010-05-27T07:34:00Z</published><updated>2010-05-27T07:34:00Z</updated><author><name>RMay</name><uri>http://www.cnblogs.com/RMay/</uri></author><link rel="alternate" href="http://www.cnblogs.com/RMay/archive/2010/05/27/1745388.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/RMay/archive/2010/05/27/1745388.html"/><content type="text">WPF中自带一个WebBrowser控件，当我们使用它打开一个网页，例如百度，然后点击它其中的链接时，如果这个链接是会弹出一个新窗口的，那么它会生生的弹出一个IE窗口来，而不是在内部跳到该链接。如果使用Winform的WebBrowser控件，我们可以监听它的NewWindow事件，在这个事件中做一些处理，例如，在新建一个Tab来打开，或者控制它在当前WebBrowser中跳转。很不幸的是，WPF...</content></entry><entry><id>http://www.cnblogs.com/RMay/archive/2009/09/02/1559035.html</id><title type="text">【WPF】如何让弹出的窗口&amp;quot;阻塞&amp;quot;</title><summary type="text">还存在一些问题，再研究一下1、ComponentDispatcher其实可以不用2、new一个DispatcherFrame其实是把一个消息循环（姑且称作嵌套消息循环）当做一个DispatchFrame来处理，在这个消息循环结束之前，原来的代码就是阻塞的3、正是因为第二个原因，如果再次弹出一个窗口，将是在前一个嵌套消息循环中，再次执行2，也就会导致第一个窗口关闭，并不会立即执行后面的代码。【场景描...</summary><published>2009-09-02T12:43:00Z</published><updated>2009-09-02T12:43:00Z</updated><author><name>RMay</name><uri>http://www.cnblogs.com/RMay/</uri></author><link rel="alternate" href="http://www.cnblogs.com/RMay/archive/2009/09/02/1559035.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/RMay/archive/2009/09/02/1559035.html"/><content type="text">还存在一些问题，再研究一下1、ComponentDispatcher其实可以不用2、new一个DispatcherFrame其实是把一个消息循环（姑且称作嵌套消息循环）当做一个DispatchFrame来处理，在这个消息循环结束之前，原来的代码就是阻塞的3、正是因为第二个原因，如果再次弹出一个窗口，将是在前一个嵌套消息循环中，再次执行2，也就会导致第一个窗口关闭，并不会立即执行后面的代码。【场景描...</content></entry><entry><id>http://www.cnblogs.com/RMay/archive/2009/06/26/1511927.html</id><title type="text">Michael去了，谁来让我Rock</title><summary type="text">仅此纪念Michael.Jackson</summary><published>2009-06-26T12:22:00Z</published><updated>2009-06-26T12:22:00Z</updated><author><name>RMay</name><uri>http://www.cnblogs.com/RMay/</uri></author><link rel="alternate" href="http://www.cnblogs.com/RMay/archive/2009/06/26/1511927.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/RMay/archive/2009/06/26/1511927.html"/><content type="text">仅此纪念Michael.Jackson</content></entry><entry><id>http://www.cnblogs.com/RMay/archive/2009/06/05/1497138.html</id><title type="text">PNG图片导致的WPF性能问题</title><summary type="text">WPF,Performance,XPE</summary><published>2009-06-05T09:04:00Z</published><updated>2009-06-05T09:04:00Z</updated><author><name>RMay</name><uri>http://www.cnblogs.com/RMay/</uri></author><link rel="alternate" href="http://www.cnblogs.com/RMay/archive/2009/06/05/1497138.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/RMay/archive/2009/06/05/1497138.html"/><content type="text">WPF,Performance,XPE</content></entry><entry><id>http://www.cnblogs.com/RMay/archive/2009/01/20/1379023.html</id><title type="text">【WPF】用CustomControl打造WPF版的Marquee</title><summary type="text">控件代码已经更新，支持上下左右四个方向。VS2010工程/Files/RMay/WPF_Marquee/WpfMarquee.zip我们知道在html中有一个marquee标签，可以很方便的实现文字滚动的效果，比如如下简单的声明：&lt;marquee loop="3" behavior="scroll"&gt;文本信息&lt;marquee&gt;在WPF里面，当然，我们可以用Animation...</summary><published>2009-01-20T09:15:00Z</published><updated>2009-01-20T09:15:00Z</updated><author><name>RMay</name><uri>http://www.cnblogs.com/RMay/</uri></author><link rel="alternate" href="http://www.cnblogs.com/RMay/archive/2009/01/20/1379023.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/RMay/archive/2009/01/20/1379023.html"/><content type="text">控件代码已经更新，支持上下左右四个方向。VS2010工程/Files/RMay/WPF_Marquee/WpfMarquee.zip我们知道在html中有一个marquee标签，可以很方便的实现文字滚动的效果，比如如下简单的声明：&lt;marquee loop="3" behavior="scroll"&gt;文本信息&lt;marquee&gt;在WPF里面，当然，我们可以用Animation...</content></entry><entry><id>http://www.cnblogs.com/RMay/archive/2009/01/14/1375666.html</id><title type="text">【WPF】在Style中设置ToolTip的问题</title><summary type="text">更新：在网上找到更正规的解决方案http://thewpfblog.com/?p=61今天在群里有人问到：“怎样设置 TextBlock.ToolTip 的width，使得过长的字符串自动换行”其实ToolTip是一个object，我们可以在其中放置任何东西，所以要解决这个问题，其实很简单，只需要写如下的xaml代码：&lt;TextBlock&gt;&lt;TextBlo...</summary><published>2009-01-14T07:17:00Z</published><updated>2009-01-14T07:17:00Z</updated><author><name>RMay</name><uri>http://www.cnblogs.com/RMay/</uri></author><link rel="alternate" href="http://www.cnblogs.com/RMay/archive/2009/01/14/1375666.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/RMay/archive/2009/01/14/1375666.html"/><content type="text">更新：在网上找到更正规的解决方案http://thewpfblog.com/?p=61今天在群里有人问到：“怎样设置 TextBlock.ToolTip 的width，使得过长的字符串自动换行”其实ToolTip是一个object，我们可以在其中放置任何东西，所以要解决这个问题，其实很简单，只需要写如下的xaml代码：&lt;TextBlock&gt;&lt;TextBlo...</content></entry><entry><id>http://www.cnblogs.com/RMay/archive/2008/12/10/1352156.html</id><title type="text">【WPF】Binding's Little Trick</title><summary type="text">今天为了帮别人解决一个3D的问题，需要将自己以前做的一个Demo发过去，结果，原来能正常运行的程序现在无法运行了。调试时报出的错误是：“无法将“System.Windows.Media.Media3D.PerspectiveCamera”值分配到对象“System.Windows.Controls.Viewport3D”的属性&amp;#8220...</summary><published>2008-12-10T09:39:00Z</published><updated>2008-12-10T09:39:00Z</updated><author><name>RMay</name><uri>http://www.cnblogs.com/RMay/</uri></author><link rel="alternate" href="http://www.cnblogs.com/RMay/archive/2008/12/10/1352156.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/RMay/archive/2008/12/10/1352156.html"/><content type="text">今天为了帮别人解决一个3D的问题，需要将自己以前做的一个Demo发过去，结果，原来能正常运行的程序现在无法运行了。调试时报出的错误是：“无法将“System.Windows.Media.Media3D.PerspectiveCamera”值分配到对象“System.Windows.Controls.Viewport3D”的属性&amp;#8220...</content></entry></feed>
