<?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>CNBlogs BlogServer</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控件，但是它是严格按照货币的格式化方式来格式化的，不适合国人的金额格式习惯。因为国人的金额格式习惯是类似于 $#,###,###.##，但是某些币种，小数点是&amp;#39;,&amp;#39;，分组符号是&amp;#39;.&amp;#39;，是反过来的，很容易让人看错；而某些币种的输入方式是从右往左，就更不适应了。因此，自己写了一</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;&#xD;
&lt;p&gt;由于项目的需要，我们在某些场合下需要对输入做限制，例如金额，需要靠右对齐，需要显示货币符号，需要显示分隔符号等等。相信大家都碰到过这种需求。上网找这种控件也很难找，要么就是收费的，要么就是不太符合国人的习惯。例如，原来用过一个第三方NetAdvantage控件，但是它是严格按照货币的格式化方式来格式化的，不适合国人的金额格式习惯。因为国人的金额格式习惯是类似于 $#,###,###.##，但是某些币种，小数点是','，分组符号是'.'，是反过来的，很容易让人看错；而某些币种的输入方式是从右往左，就更不适应了。&lt;/p&gt;&#xD;
&lt;p&gt;因此，自己写了一个金额输入控件CurrencyEditor，可以根据不同的语言显示不同的货币符号和限制小数位数。没有直接用.Net的格式化decimal，而是自己调用.Net格式化之后，再处理为&amp;ldquo;货币符号+金额值&amp;rdquo;的形式。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img src="http://pic002.cnblogs.com/images/2011/35870/2011040309460195.png" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;CurrencyEditor继承自TextBox，要点是在OnTextChanged中去解析文本是否合法，并且将文本格式化，然后设置光标的位置。其实TextBox还有一个TextInput事件，但是在这个事件中处理的问题在于，复制粘贴操作不会触发TextInput，会导致用户可以用复制粘贴的方式录入非法文本。其次，就是在OnSelectionChanged中去检查光标的位置，要保证用户录入的舒适性。在OnPreviewKeyDown中处理一些非法录入，和控制光标位置，例如按下'.'直接跳到小数点之后，同时控制用户通过DEL和Backspace不会去删除掉货币符号和小数点。详情还是见代码吧，注释很详尽。&lt;/p&gt;&#xD;
&lt;p&gt;另外一个控件是限制输入的FieldTextBox，限制有两方面，一个是输入的内容，有Text和Digit两种。Text可以任意输入，Digit只能输入数字（例如，在输入卡号的时候很有用）。另一个是限制输入的字节长度，这个限制在输入一个报文中，按照字节有长度限制的字段时很有用。WPF的TextBox虽然有一个MaxLength，但是限制的是字符长度。例如，&amp;ldquo;我&amp;rdquo;是两个字节，却只是一个字符。FieldTextBox的处理逻辑与CurrencyEditor类似，但是要稍微简单一点。&lt;/p&gt;&#xD;
&lt;p&gt;附代码，跟大家分享一下:)&lt;/p&gt;&#xD;
&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;&#xD;
&lt;p&gt;先给个效果图：&lt;/p&gt;&#xD;
&lt;p style="text-indent: 0px; margin: 5px auto;"&gt;&lt;img src="http://pic002.cnblogs.com/images/2010/35870/2010122716310865.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;使用时的代码：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;" onclick="cnblogs_code_show('d838208f-60c3-478f-a2bd-e2466accc93a')"&gt;&#xD;
&lt;div id="cnblogs_code_open_d838208f-60c3-478f-a2bd-e2466accc93a"&gt;&#xD;
&lt;pre&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;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;------------------------正文-------------------------------&lt;/p&gt;&#xD;
&lt;div&gt;&lt;span &gt;&lt;span &gt;&#xD;
&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;&#xD;
&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&#xD;
&lt;p style="text-indent: 0px; margin: 5px auto;"&gt;对这个问题，首先能想到的解决办法是，在GridViewColumn的CellTemplate中，放上一个Border，然后设置Border的BorderBrush和BorderThickness。例如：&lt;/p&gt;&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;" 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;&#xD;
&lt;pre&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;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p style="text-indent: 0px; margin: 5px auto;"&gt;&lt;/p&gt;&#xD;
&lt;p style="text-indent: 0px; margin: 5px auto;"&gt;但是，很快你会发现，Border不能随着列宽的变化而变化，就像这样：&lt;/p&gt;&#xD;
&lt;p style="text-indent: 0px; margin: 5px auto;"&gt;&lt;img style="border-width: 0px;" src="http://pic002.cnblogs.com/images/2010/35870/2010122716004992.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p style="text-indent: 0px; margin: 5px auto;"&gt;而且，即使将ListView的HorizontalContentAlignment置为Stretch，也不能起到作用。必须在ListViewItem上设置HorizontalContentAlignment="True"。因此，必须添加一个ListViewItem的样式，统一指定：&lt;/p&gt;&#xD;
&lt;p style="text-indent: 0px; margin: 5px auto;"&gt;&lt;/p&gt;&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;" 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;&#xD;
&lt;pre&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;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p style="text-indent: 0px; margin: 5px auto;"&gt;但问题还是没有解决，因为Border不能填满整个Cell，就像这样：&lt;/p&gt;&#xD;
&lt;p style="text-indent: 0px; margin: 5px auto;"&gt;&lt;img style="border-width: 0px;" src="http://pic002.cnblogs.com/images/2010/35870/2010122716044035.png" alt="" /&gt;&lt;/p&gt;&#xD;
&lt;p style="text-indent: 0px; margin: 5px auto;"&gt;于是，你得小心的设置各个Border的Margin，来让它们&amp;ldquo;恰好&amp;rdquo;都连在一起，看上去就像是连续的线条。也许调整Margin还不够，还得修改ListViewItem的模板；模板修改好了，发现创建这么多的Border性能又跟不上；最头大的是，每个Column都要指定一次CellTemplate，万一哪天边线的颜色要统一调整一下&amp;hellip;&amp;hellip;&lt;/p&gt;&#xD;
&lt;p style="text-indent: 0px; margin: 5px auto;"&gt;因此，这种办法固然可行，操作起来其实麻烦的要死。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 0px; margin: 5px auto;"&gt;&lt;/p&gt;&#xD;
&lt;p style="text-indent: 0px; margin: 5px auto;"&gt;有没有一种方式，可以直接在ListView上&amp;ldquo;画线&amp;rdquo;呢？固然，我们可以自己写一个ListView，在OnRender里面画线什么的，但理想的情况还是能够在可以不改动任何现有控件的条件下，实现这个画网格的功能。同时，这个网格线的颜色可以随意调整就更好了。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 0px; margin: 5px auto;"&gt;因此，总的要求如下：&lt;/p&gt;&#xD;
&lt;p style="text-indent: 0px; margin: 5px auto;"&gt;1、可以画网格&lt;/p&gt;&#xD;
&lt;p style="text-indent: 0px; margin: 5px auto;"&gt;2、不用改动ListView，或者自己写ListView&lt;/p&gt;&#xD;
&lt;p style="text-indent: 0px; margin: 5px auto;"&gt;3、可以调整网格的颜色&lt;/p&gt;&#xD;
&lt;p style="text-indent: 0px; margin: 5px auto;"&gt;&lt;/p&gt;&#xD;
&lt;p style="text-indent: 0px; margin: 5px auto;"&gt;如果对设计模式熟悉的话，&amp;ldquo;不改动现有代码，增加新的功能&amp;rdquo;，应该马上能够想到装饰器模式。其实，WPF中本身就有Decorator这个控件，而常用的Border就是一个Decorator，可以帮助控件画背景色，画边线等等。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 0px; margin: 5px auto;"&gt;因此，如果能够有这么一个Decorator，把ListView往里面一放，就能有画线的功能，岂不快哉？不过，这里我并不打算直接继承Decorator来修改，因为WPF提供的Decorator是针对所有UIElment的，而我们只想针对ListView。&lt;/p&gt;&#xD;
&lt;p style="text-indent: 0px; margin: 5px auto;"&gt;GridLineDecorator直接继承自FrameworkElement，并且通过重载VisualChild和LogicalChild相关的代码来显示其包装的ListView。&amp;nbsp;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;span  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  style="line-height: 21px; font-family: verdana, 'courier new'; font-size: 14px;"&gt;&#xD;
&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;" onclick="cnblogs_code_show('3605217b-a861-4561-b820-769f70f644c8')"&gt;&#xD;
&lt;div id="cnblogs_code_open_3605217b-a861-4561-b820-769f70f644c8" &gt;&#xD;
&lt;pre&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;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;其中，Target是一个属性，类型是ListView，而有一个_guidLinesVisual，则是用于绘制网格的DrawingVisual。有人可能会问，为什么不直接重载OnRender方法，在里面画线呢？&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;理由是，重载OnRender方法画线，当ListView设置了背景后，会将我们画的线盖住。这是因为控件的背景是在模板中放了一个Border来绘制的，Border也是在OnRender中绘制的，它后绘制，我们的先绘制，会将我们画的线给盖住。同时，你会发现，当ListView的Column改变大小的时候，并不会引起GridLineDecorator重绘，所以网格线无法同步变化。&lt;/p&gt;&#xD;
&lt;p&gt;其实，GridLineDecorator里面的GetVisualChild重载也非常讲究：&lt;/p&gt;&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;" onclick="cnblogs_code_show('c0ff86d8-3bd1-4265-9d31-f684535374bb')"&gt;&#xD;
&lt;div id="cnblogs_code_open_c0ff86d8-3bd1-4265-9d31-f684535374bb"&gt;&#xD;
&lt;pre&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;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;/div&gt;&#xD;
&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;&#xD;
&lt;p&gt;在经过一番研究之后，终于找到了一个可行的办法，监听ScrollViewer的ScrollChanged事件，因为ListView内部是放置了两个ScrollViewer，一个用于显示Header，一个用于显示Items。当Column的宽度变化时，会触发ScrollViewer的ScrollChanged事件。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;因此，在构造函数里面：&lt;/p&gt;&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;" onclick="cnblogs_code_show('76b58736-a0ab-4878-b75b-85855a585ae7')"&gt;&#xD;
&lt;div id="cnblogs_code_open_76b58736-a0ab-4878-b75b-85855a585ae7"&gt;&#xD;
&lt;pre&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;/pre&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;/div&gt;&#xD;
&lt;p&gt;画线的逻辑，主要就是遍历所有的Container（其实是ListViewItem），计算其相对于GridLineDecorator的位移，算出横线和纵线的坐标和长度，画线。代码比较多，大家可以下载以后自己看。&lt;/p&gt;&#xD;
&lt;p&gt;细心的童鞋可能会发现，有时候底部的线条在ListViewItem显示不完整时，没有画到最下端，这是由于ListView做了Virtualize处理。大家可以设置VirtualizingStackPanel.IsVirtualizing="False"来强制绘制。&lt;/p&gt;&#xD;
&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;amp;page=1&amp;amp;extra=#pid6692WPF 4.0的DatePicker在通过键盘录入日期的时候是非常让人郁闷的。必须按照日期的格式来完整输入例如，比如输入&amp;#8220;2010/10/10&amp;#8221;才能识别。而实际上在一些要求快速录入的...</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="html">&lt;p&gt;先发表在&lt;a href="http://www.bbniu.com/forum" target="_blank"&gt;棒棒牛&lt;/a&gt;了，转过来吧。&lt;/p&gt;&#xD;
&lt;p&gt;传送门：&lt;a href="http://www.bbniu.com/forum/viewthread.php?tid=752&amp;amp;page=1&amp;amp;extra=#pid6692" target="_blank"&gt;http://www.bbniu.com/forum/viewthread.php?tid=752&amp;amp;page=1&amp;amp;extra=#pid6692&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;WPF 4.0的DatePicker在通过键盘录入日期的时候是非常让人郁闷的。必须按照日期的格式来完整输入&lt;br /&gt;例如，比如输入&amp;#8220;2010/10/10&amp;#8221;才能识别。而实际上在一些要求快速录入的场合，用户更希望直接敲20101010就行了。&lt;br /&gt;遗憾的是，DatePicker没有一个属性可以设置说录入的格式是yyyyMMdd这种的。&lt;br /&gt;&lt;br /&gt;实际上，仔细看一下DatePicker控件，它有一个DateValidationError事件，当输入的文本无法识别为日期时，就会触发该事件。我们可以利用这个事件来做一些事情。&lt;br /&gt;&lt;br /&gt;为了方便使用，我们可以封装一个附加属性，在需要快速录入的地方Attach一下就好了。&lt;br /&gt;&lt;br /&gt;public static readonly DependencyProperty EnableFastInputProperty =&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;DependencyProperty.RegisterAttached("EnableFastInput", typeof(bool), typeof(DatePickerHelper),&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; new FrameworkPropertyMetadata((bool)false,&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; new PropertyChangedCallback(OnEnableFastInputChanged)));&lt;br /&gt;&lt;br /&gt;public static bool GetEnableFastInput(DependencyObject d)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; return (bool)d.GetValue(EnableFastInputProperty);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public static void SetEnableFastInput(DependencyObject d, bool value)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; d.SetValue(EnableFastInputProperty, value);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;这样，我们就给一个DatePickerHelper类型注册了一个附加属性，叫做EnableFastInput。&lt;br /&gt;在这个属性的PropertyChanged事件处理函数中，我们监听DatePicker的DateValidationError事件&lt;br /&gt;private static void OnEnableFastInputChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;var datePicker = d as DatePicker;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;if (datePicker != null)&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;if ((bool)e.NewValue)&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;datePicker.DateValidationError += DatePickerOnDateValidationError;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;else&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;datePicker.DateValidationError -= DatePickerOnDateValidationError;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;在事件处理中，我们尝试着解析文本，并且设置日期：&lt;br /&gt;private static void DatePickerOnDateValidationError(object sender, DatePickerDateValidationErrorEventArgs e)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; var datePicker = sender as DatePicker;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; if (datePicker != null)&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; var text = e.Text;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; DateTime dateTime;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; if (DateTime.TryParseExact(text, "yyyyMMdd", CultureInfo.CurrentUICulture, DateTimeStyles.None, out dateTime))&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; {&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; datePicker.SelectedDate = dateTime;&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;在Xaml中使用时：&lt;br /&gt;&amp;lt;DatePicker l:DatePickerHelper.EnabledFastInput="True"/&amp;gt;&lt;br /&gt;&lt;br /&gt;这样，DatePicker就支持直接输入yyyyMMdd格式的日期了。&lt;br /&gt;当然，这里的日期格式是写死的，可以考虑封装成另外一个DatePickerHelper.InputDateFormat属性之类的，更加灵活&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;【效果图】&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img border="0" alt="" src="http://images.cnblogs.com/cnblogs_com/rmay/WPF_DatePicker/输入.png" width="525" height="350" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img border="0" alt="" src="http://images.cnblogs.com/cnblogs_com/rmay/WPF_DatePicker/回车.png" width="525" height="350" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;【代码】&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://files.cnblogs.com/RMay/WpfDatePicker.zip" target="_blank"&gt;/Files/RMay/WpfDatePicker.zip&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/RMay/aggbug/1745636.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/RMay/archive/2010/05/27/1745636.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</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="html">&lt;p&gt;WPF中自带一个WebBrowser控件，当我们使用它打开一个网页，例如百度，然后点击它其中的链接时，如果这个链接是会弹出一个新窗口的，那么它会生生的弹出一个IE窗口来，而不是在内部跳到该链接。&lt;br /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;如果使用Winform的WebBrowser控件，我们可以监听它的NewWindow事件，在这个事件中做一些处理，例如，在新建一个Tab来打开，或者控制它在当前WebBrowser中跳转。很不幸的是，WPF的WebBrowser没有这个事件。&lt;/p&gt;&#xD;
&lt;p&gt;说到底，Winform的WB或者是WPF的WB都是在调用IE的一个控件，因此，Winform能加上的，我们WPF一定也有办法加上。如此，那我们就请出神器Reflector，研究一把。&lt;/p&gt;&#xD;
&lt;p&gt;首先，我们打开Winform的WebBrowser，找到触发NewWindow事件的代码：&lt;br /&gt;&lt;/p&gt;&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;"&gt;&#xD;
&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;protected&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;OnNewWindow(CancelEventArgs&amp;nbsp;e)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;if&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;(&lt;/span&gt;&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;&lt;span style="color: #000000"&gt;.NewWindow&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;!=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;null&lt;/span&gt;&lt;span style="color: #000000"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;&lt;span style="color: #000000"&gt;.NewWindow(&lt;/span&gt;&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;&lt;span style="color: #000000"&gt;,&amp;nbsp;e);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;它是在OnNewWindow方法中触发的。那么，是谁调用了这个OnNewWindow呢？接着搜索，最后在一个叫WebBrowserEvent的类里面发现这么一段：&lt;br /&gt;&lt;/p&gt;&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;"&gt;&#xD;
&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;public&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;NewWindow2(&lt;/span&gt;&lt;span style="color: #0000ff"&gt;ref&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;ppDisp,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;ref&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;bool&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;cancel)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CancelEventArgs&amp;nbsp;e&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;new&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;CancelEventArgs();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;&lt;span style="color: #000000"&gt;.parent.OnNewWindow(e);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cancel&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;e.Cancel;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;我们接着搜NewWindow2，却发现没有地方显式地调用它了。既然从方法入手没找到，那我们就来研究一下定义这个方法的WebBrowserEvent，看看是谁在使用它。&lt;br /&gt;仔细搜索一遍，最后发现在WebBrowser的CreateSink方法中有这么一段：&lt;br /&gt;&lt;/p&gt;&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;" onclick="cnblogs_code_show('f8d3f2d8-c461-4bc2-9823-939195364c58')"&gt;&lt;img style="display: none" id="code_img_opened_f8d3f2d8-c461-4bc2-9823-939195364c58"  onclick="cnblogs_code_hide('f8d3f2d8-c461-4bc2-9823-939195364c58',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"&gt;&#xD;
&lt;div id="cnblogs_code_open_f8d3f2d8-c461-4bc2-9823-939195364c58" &gt;&#xD;
&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;protected&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;override&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;CreateSink()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;activeXInstance&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;base&lt;/span&gt;&lt;span style="color: #000000"&gt;.activeXInstance;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;if&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;(activeXInstance&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;!=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;null&lt;/span&gt;&lt;span style="color: #000000"&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;&lt;span style="color: #000000"&gt;.webBrowserEvent&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;new&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;WebBrowserEvent(&lt;/span&gt;&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;&lt;span style="color: #000000"&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;&lt;span style="color: #000000"&gt;.webBrowserEvent.AllowNavigation&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;&lt;span style="color: #000000"&gt;.AllowNavigation;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;&lt;span style="color: #000000"&gt;.cookie&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;new&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;AxHost.ConnectionPointCookie(activeXInstance,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;&lt;span style="color: #000000"&gt;.webBrowserEvent,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;&lt;span style="color: #000000"&gt;(UnsafeNativeMethods.DWebBrowserEvents2));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;注意这句话：&lt;br /&gt;&lt;/p&gt;&#xD;
&lt;p style="font-weight: bold"&gt;this.cookie = new AxHost.ConnectionPointCookie(activeXInstance, this.webBrowserEvent, typeof(UnsafeNativeMethods.DWebBrowserEvents2));&lt;/p&gt;&#xD;
&lt;p&gt;很显然，这句话是关键。AxHost.ConnectionPointCookie类的作用是：&amp;#8220;将一个ActiveX 控件连接到处理该控件的事件的客户端&amp;#8221;。&lt;br /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;上面的调用中有一个很奇怪的类型：DWebBrowserEvents2，熟悉COM的童鞋应该马上能想到，这其实是一个COM类型的定义。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;" onclick="cnblogs_code_show('daf5ec48-434e-4d59-a2c5-5d654509e802')"&gt;&lt;img id="code_img_opened_daf5ec48-434e-4d59-a2c5-5d654509e802"  onclick="cnblogs_code_hide('daf5ec48-434e-4d59-a2c5-5d654509e802',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"&gt;&#xD;
&lt;div id="cnblogs_code_open_daf5ec48-434e-4d59-a2c5-5d654509e802"&gt;&#xD;
&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;[ComImport,&amp;nbsp;TypeLibType(TypeLibTypeFlags.FHidden),&amp;nbsp;InterfaceType(ComInterfaceType.InterfaceIsIDispatch),&amp;nbsp;Guid(&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #800000"&gt;34A715A0-6587-11D0-924A-0020AFC7AC4D&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;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;interface&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;DWebBrowserEvents2&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;......&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;} &lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;实际上，我们再去看WebBrowserEvent的定义，它恰恰是实现了这个接口的。&lt;br /&gt;&lt;/p&gt;&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;"&gt;&#xD;
&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;[ClassInterface(ClassInterfaceType.None)]&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;WebBrowserEvent&amp;nbsp;:&amp;nbsp;StandardOleMarshalObject,&amp;nbsp;UnsafeNativeMethods.DWebBrowserEvents2&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;......&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;因此，上面这句话不难理解，就是定义一个实现了特定COM接口的类型，让浏览器控件的事件能够转发到这个类型实例去处理。因此，NewWindow2其实是浏览器控件去调用的。&lt;br /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Winform的WebBrowser我们搞清楚了，下面我们来看WPF的。其实，打开WPF的WebBrowser代码之后，我们会发现它跟Winform的WebBrowser机制是一样的。一个似曾相识的CreateSink方法映入眼中：&lt;br /&gt;&lt;/p&gt;&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;" onclick="cnblogs_code_show('a1c1250f-5018-4d34-96db-fdd04a37d0c4')"&gt;&lt;img id="code_img_opened_a1c1250f-5018-4d34-96db-fdd04a37d0c4"  onclick="cnblogs_code_hide('a1c1250f-5018-4d34-96db-fdd04a37d0c4',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"&gt;&#xD;
&lt;div id="cnblogs_code_open_a1c1250f-5018-4d34-96db-fdd04a37d0c4"&gt;&#xD;
&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;[SecurityTreatAsSafe,&amp;nbsp;SecurityCritical]&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;internal&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;override&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;CreateSink()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;&lt;span style="color: #000000"&gt;._cookie&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;new&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;ConnectionPointCookie(&lt;/span&gt;&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;&lt;span style="color: #000000"&gt;._axIWebBrowser2,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;&lt;span style="color: #000000"&gt;._hostingAdaptor.CreateEventSink(),&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;&lt;span style="color: #000000"&gt;(UnsafeNativeMethods.DWebBrowserEvents2));&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;这儿也有一个ConnectionPointCookie，但是它的访问权限是internal的:(&lt;br /&gt;第二个参数，_hostingAdapter.CreateEventSink返回的是什么呢：&lt;br /&gt;&lt;/p&gt;&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;" onclick="cnblogs_code_show('09e7418f-8527-40ee-b02d-aff79fb53d51')"&gt;&lt;img style="display: none" id="code_img_opened_09e7418f-8527-40ee-b02d-aff79fb53d51"  onclick="cnblogs_code_hide('09e7418f-8527-40ee-b02d-aff79fb53d51',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"&gt;&#xD;
&lt;div id="cnblogs_code_open_09e7418f-8527-40ee-b02d-aff79fb53d51" &gt;&#xD;
&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;[SecurityCritical]&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;internal&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;CreateEventSink()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;return&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;new&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;WebBrowserEvent(&lt;/span&gt;&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;&lt;span style="color: #000000"&gt;._webBrowser);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[ClassInterface(ClassInterfaceType.None)]&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;internal&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;WebBrowserEvent&amp;nbsp;:&amp;nbsp;InternalDispatchObject&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #000000"&gt;UnsafeNativeMethods.DWebBrowserEvents2&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;,&amp;nbsp;UnsafeNativeMethods.DWebBrowserEvents2&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;......&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;仍然是一个WebBrowserEvent！悲剧的是，这个WPF的WebBrowserEvent，并没有触发NewWindowEvent：&lt;br /&gt;&lt;/p&gt;&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;"&gt;&#xD;
&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;public&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;NewWindow2(&lt;/span&gt;&lt;span style="color: #0000ff"&gt;ref&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;ppDisp,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;ref&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;bool&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;cancel)&lt;br /&gt;{&lt;br /&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;现在知道为什么WPF的WB控件没有NewWindow事件了吧？微软的童鞋压根儿就没写！&lt;br /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;既然微软的童鞋不写，那我们就自己折腾一把，反正原理已经搞清楚了。&lt;/p&gt;&#xD;
&lt;p&gt;首先，我们也得定义一个DWebBrowserEvents2接口，这个我们直接通过Reflector复制一份就好了。代码就不贴上来了。&lt;/p&gt;&#xD;
&lt;p&gt;接着，我们再仿造一个WebBrowserEvent，关键是要触发NewWindow事件：&lt;/p&gt;&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;" onclick="cnblogs_code_show('0996f75f-44e5-4f53-8173-a14f3fd5f25d')"&gt;&lt;img id="code_img_opened_0996f75f-44e5-4f53-8173-a14f3fd5f25d"  onclick="cnblogs_code_hide('0996f75f-44e5-4f53-8173-a14f3fd5f25d',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"&gt;&#xD;
&lt;div id="cnblogs_code_open_0996f75f-44e5-4f53-8173-a14f3fd5f25d"&gt;&#xD;
&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;public&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;partial&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;WebBrowserHelper&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;class&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;WebBrowserEvent&amp;nbsp;:&amp;nbsp;StandardOleMarshalObject,&amp;nbsp;DWebBrowserEvents2&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;private&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;WebBrowserHelper&amp;nbsp;_helperInstance&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;WebBrowserEvent(WebBrowserHelper&amp;nbsp;helperInstance)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_helperInstance&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;helperInstance;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;......&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;public&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;NewWindow2(&lt;/span&gt;&lt;span style="color: #0000ff"&gt;ref&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;pDisp,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;ref&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;bool&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;cancel)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_helperInstance.OnNewWindow(&lt;/span&gt;&lt;span style="color: #0000ff"&gt;ref&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;cancel);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;......&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;最后，我们需要仿造Framework中的代码，也来CreateSink一把（我承认，用了反射来取WebBrowser内部的东东，谁让这些类型都是internal的呢）：&lt;/p&gt;&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;" onclick="cnblogs_code_show('87fdd57a-f98b-4c4f-93d7-1fa35d4b9524')"&gt;&lt;img id="code_img_opened_87fdd57a-f98b-4c4f-93d7-1fa35d4b9524"  onclick="cnblogs_code_hide('87fdd57a-f98b-4c4f-93d7-1fa35d4b9524',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"&gt;&#xD;
&lt;div id="cnblogs_code_open_87fdd57a-f98b-4c4f-93d7-1fa35d4b9524"&gt;&#xD;
&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;private&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;Attach()&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;axIWebBrowser2&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;_webBrowser.ReflectGetProperty(&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #800000"&gt;AxIWebBrowser2&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: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;webBrowserEvent&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;new&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;WebBrowserEvent(&lt;/span&gt;&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;&lt;span style="color: #000000"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;cookieType&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;&lt;span style="color: #000000"&gt;(WebBrowser).Assembly.GetType(&lt;/span&gt;&lt;span style="color: #800000"&gt;"&lt;/span&gt;&lt;span style="color: #800000"&gt;MS.Internal.Controls.ConnectionPointCookie&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: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_cookie&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;Activator.CreateInstance(&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cookieType,&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ReflectionService.BindingFlags,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;null&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;new&lt;/span&gt;&lt;span style="color: #000000"&gt;[]&amp;nbsp;{&amp;nbsp;axIWebBrowser2,&amp;nbsp;webBrowserEvent,&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;&lt;span style="color: #000000"&gt;(DWebBrowserEvents2)&amp;nbsp;},&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CultureInfo.CurrentUICulture);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;最后的使用：&lt;br /&gt;&lt;/p&gt;&#xD;
&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;"&gt;&#xD;
&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;var&amp;nbsp;webBrowserHelper&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;new&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;WebBrowserHelper(webBrowser);&lt;br /&gt;......&lt;br /&gt;webBrowserHelper.NewWindow&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000"&gt;+=&lt;/span&gt;&lt;span style="color: #000000"&gt;&amp;nbsp;WebBrowserOnNewWindow;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&#xD;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;【效果图】&lt;/p&gt;&#xD;
&lt;p&gt;初始网页：&lt;/p&gt;&#xD;
&lt;p&gt;&lt;img border="0" alt="" src="http://images.cnblogs.com/cnblogs_com/rmay/WPF_WebBrowser/初始网页.png" width="400" height="292" /&gt;&lt;br /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;点击一个链接，默认情况下，将是弹出一个IE窗口，现在是在新的Tab中打开：&lt;br /&gt;&lt;img border="0" alt="" src="http://images.cnblogs.com/cnblogs_com/rmay/WPF_WebBrowser/弹出窗口在Tab中打开.png" width="400" height="292" /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;【示例代码】&lt;/p&gt;&#xD;
&lt;p&gt;（新建按钮点击后，请输入完整的网址，例如:http://www.sina.com）&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://files.cnblogs.com/RMay/WpfWebBrowser.zip" target="_blank"&gt;/Files/RMay/WpfWebBrowser.zip&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/RMay/aggbug/1745388.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/RMay/archive/2010/05/27/1745388.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</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"/></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"/></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"/></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标签，可以很方便的实现文字滚动的效果，比如如下简单的声明：&amp;lt;marquee loop="3" behavior="scroll"&amp;gt;文本信息&amp;lt;marquee&amp;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"/></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今天在群里有人问到：&amp;#8220;怎样设置 TextBlock.ToolTip 的width，使得过长的字符串自动换行&amp;#8221;其实ToolTip是一个object，我们可以在其中放置任何东西，所以要解决这个问题，其实很简单，只需要写如下的xaml代码：&amp;lt;TextBlock&amp;gt;&amp;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"/></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发过去，结果，原来能正常运行的程序现在无法运行了。调试时报出的错误是：&amp;#8220;无法将&amp;#8220;System.Windows.Media.Media3D.PerspectiveCamera&amp;#8221;值分配到对象&amp;#8220;System.Windows.Controls.Viewport3D&amp;#8221;的属性&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"/></entry></feed>
