<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Jason Prickett's Blog : WPF</title><link>http://blogs.msdn.com/jpricket/archive/tags/WPF/default.aspx</link><description>Tags: WPF</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>CollapsibleSection - Hiding Paragraphs until the user wants to see them in a FlowDocument</title><link>http://blogs.msdn.com/jpricket/archive/2009/04/23/collapsiblesection-hiding-paragraphs-until-the-user-wants-to-see-them-in-a-flowdocument.aspx</link><pubDate>Thu, 23 Apr 2009 16:39:10 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9564745</guid><dc:creator>Jason Prickett</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/jpricket/comments/9564745.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jpricket/commentrss.aspx?PostID=9564745</wfw:commentRss><description>&lt;p&gt;As I mentioned back in &lt;a href="http://blogs.msdn.com/jpricket/archive/2009/01/07/wpf-flowdocuments-when-why-how.aspx"&gt;January&lt;/a&gt;, I created a collapsible section for use in a flow document. In my case, I was removing a treeView and replacing it with indented paragraphs in a flow document (see the previous post as to why). Some of the data that was now shown to the user all the time was rather useless in most cases. So, I had some suggestions to put back the tree. Well, I just didn’t want to lose my beautiful new FlowDocument, so I started experimenting. I noticed that a Section could contain paragraphs or any other type of Block. Naturally, I wondered how hard it would be to create a section that only showed its contained children when some property was changed. So, I wrote the code and this is how it turned out…&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;internal class CollapsibleSection : Section      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public CollapsibleSection()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CollapsibleBlocks = new List&amp;lt;Block&amp;gt;();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Header = new Paragraph();&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_expandCollapseToggleButton = new ToggleButton();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_expandCollapseToggleButton.Click += new RoutedEventHandler(ExpandCollapseToggleButton_Click);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_inlineUIContainer = new InlineUIContainer(m_expandCollapseToggleButton);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_inlineUIContainer.BaselineAlignment = BaselineAlignment.Center;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_inlineUIContainer.Cursor = Cursors.Arrow; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Header.Inlines.Add(m_inlineUIContainer);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;&amp;#160;&amp;#160;&amp;#160; private void ExpandCollapseToggleButton_Click(object sender, RoutedEventArgs e)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Invalidate();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;&amp;#160;&amp;#160;&amp;#160; public Paragraph Header { get; private set; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public List&amp;lt;Block&amp;gt; CollapsibleBlocks { get; private set; } &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;&amp;#160;&amp;#160;&amp;#160; public bool IsCollapsed      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; get       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return !(m_expandCollapseToggleButton.IsChecked ?? false);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; set       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_expandCollapseToggleButton.IsChecked = !value;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;&amp;#160;&amp;#160;&amp;#160; public void Invalidate()      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Blocks.Clear(); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (CollapsibleBlocks.Count == 0)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; m_expandCollapseToggleButton.IsChecked = null;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Blocks.Add(Header); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (!IsCollapsed)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Blocks.AddRange(CollapsibleBlocks);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;&amp;#160;&amp;#160;&amp;#160; private ToggleButton m_expandCollapseToggleButton;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private InlineUIContainer m_inlineUIContainer;       &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;As you can see, it was fairly easy to create this class. Not very much code at all. The class has a Header property that is the one paragraph that you see all the time and contains the toggle button. It also has a CollapsibleBlocks property that you can add any type of Block to. When the user clicks the button the IsCollapsed property is toggled and the Header and CollapsibleBlocks are used to modify the built-in Blocks property of the section.&lt;/p&gt;  &lt;p&gt;I left out all the work I did after the fact to make the toggle button look like a triangle and rotate when clicked, but you should be able to figure that stuff out the same way I did, by looking at the way a TreeView works.&lt;/p&gt;  &lt;p&gt;And here’s how I used the class:&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;&amp;#160;&amp;#160; CollapsibleSection section = new CollapsibleSection();      &lt;br /&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;&amp;#160;&amp;#160; &lt;/font&gt;section.Margin = new Thickness(parentIndent, StandardPadding, 0, 0);       &lt;br /&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;&amp;#160;&amp;#160; &lt;/font&gt;section.IsCollapsed = false; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;. . .&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;section.Header.Inlines.Add(header); &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;. . . &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;section.CollapsibleBlocks.Add(new Paragraph(new Run(“test paragraph”));&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font face="Courier New" color="#c0c0c0" size="2"&gt;section.Invalidate();&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;I don’t like having to invalidate the section after I have added everything, but I didn’t want to spend a lot of time trying to figure out a clever way around it.&lt;/p&gt;  &lt;p&gt;I hope this gives you an example of just how extensible FlowDocuments are and why I like them so much!!!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9564745" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jpricket/archive/tags/WPF/default.aspx">WPF</category></item><item><title>WPF Documents - Indenting Paragraphs</title><link>http://blogs.msdn.com/jpricket/archive/2009/01/07/wpf-documents-indenting-paragraphs.aspx</link><pubDate>Wed, 07 Jan 2009 18:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9287652</guid><dc:creator>Jason Prickett</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/jpricket/comments/9287652.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jpricket/commentrss.aspx?PostID=9287652</wfw:commentRss><description>&lt;P&gt;As I promised, this is a post about what I learned while creating a flow document that had indented paragraphs. The hierarchy was dynamically built based on the data.&lt;/P&gt;
&lt;P&gt;The first thing I noticed is that indenting a paragraph is very easy, just set the left margin of the paragraph and the entire paragraph will be indented. If you want just the first line of the paragraph indented, simply&amp;nbsp;set the TextIndent property. In either case, the value is a double that represents WPF device indendependent units. If you want the first line to be outdenting, or you simply want a hanging indent. You have to set the left margin to the hanging indent value and then set the TextIndent to the negative of that value.&lt;/P&gt;
&lt;P&gt;Another way to indent a paragraph is to add it to a section that has the left margin set. Sections don't have a TextIndent property, but a&amp;nbsp;section can contain another section (unlike paragraphs). So, If you nested 3 sections that all had an indent of 20.0, the result would be that the inner most section would be indented 60.0 units from the left edge of the window. I didn't use this approach because I didn't have to. It was simple enough for me to simply indent each paragraph accordingly.&lt;/P&gt;
&lt;P&gt;So, that's a lot of talking without any code or pictures. Here is some XAML to demonstrate indenting:&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&amp;lt;FlowDocumentScrollViewer&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;FlowDocument&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Section&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Paragraph&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; This paragraph is not indented in any way and should wrap normally. This paragraph is not indented in any way and should wrap normally. This paragraph is not indented in any way and should wrap normally.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Paragraph&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Section&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Section&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Paragraph TextIndent="50"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; The first line of this paragraph is indented by 50 units, but the rest of the lines will not indent at all. The first line of this paragraph is indented by 50 units, but the rest of the lines will not indent at all.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Paragraph&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Section&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Section&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Paragraph TextIndent="-50" Margin="50,20,0,0"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; The first line of this paragraph is not indented, but the rest of the lines will be indented by 50 units. The first line of this paragraph is not indented, but the rest of the lines will be indented by 50 units.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Paragraph&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Section&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Section&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Paragraph Margin="50,20,0,0"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; This paragraph is indented by 50 units, but the section is not indented at all. This paragraph is indented by 50 units, but the section is not indented at all. This paragraph is indented by 50 units, but the section is not indented at all.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Paragraph&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Paragraph Margin="100,0,0,0"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; This paragraph is indented by 100 units, but the section is not indented at all. This paragraph is indented by 100 units, but the section is not indented at all. This paragraph is indented by 100 units, but the section is not indented at all.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Paragraph&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Section&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Section Margin="50,20,0,0"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Paragraph Margin="0,0,0,0"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; This paragraph is not indented, but the section is indented by 50 units. This paragraph is not indented, but the section is indented by 50 units. This paragraph is not indented, but the section is indented by 50 units.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Paragraph&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Paragraph Margin="50,0,0,0"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; This paragraph is indented by 50 units, but the section is also indented by 50 units. This paragraph is indented by 50 units, but the section is also indented by 50 units. This paragraph is indented by 50 units, but the section is also indented by 50 units.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Paragraph&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Section&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Section Margin="50,20,0,0"&amp;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;&amp;nbsp; &amp;lt;Section Margin="50,0,0,0"&amp;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;&amp;nbsp; &amp;lt;Paragraph Margin="0,0,0,0"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; This paragraph is not indented, but it is in a nested section that is indented by 50 units and the outer section is also indented by 50 units - that makes 100 units total for this paragraph.&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;&amp;nbsp; &amp;lt;/Paragraph&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Section&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/Section&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/FlowDocument&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;lt;/FlowDocumentScrollViewer&amp;gt;&lt;BR&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9287652" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jpricket/archive/tags/WPF/default.aspx">WPF</category></item><item><title>WPF FlowDocuments - What, When, Why, How?</title><link>http://blogs.msdn.com/jpricket/archive/2009/01/07/wpf-flowdocuments-when-why-how.aspx</link><pubDate>Wed, 07 Jan 2009 16:53:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9287433</guid><dc:creator>Jason Prickett</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/jpricket/comments/9287433.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jpricket/commentrss.aspx?PostID=9287433</wfw:commentRss><description>&lt;P&gt;As I learn more and more about WPF, I am continually amazed at how much I don't know. I recently discovered FlowDocuments (look &lt;A class="" title="WPF Flow Document" href="http://msdn.microsoft.com/en-us/library/aa970909.aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa970909.aspx"&gt;here&lt;/A&gt; for more info on the basics of FlowDocuments)&amp;nbsp;and how wonderful they are. Okay, I knew about them a little, but I ignored them because I didn't think you could do very much with them other than present text to the user. Well how wrong I was!&lt;/P&gt;
&lt;P&gt;&lt;U&gt;&lt;STRONG&gt;Why?&lt;/STRONG&gt;&amp;nbsp;&lt;/U&gt;&lt;/P&gt;
&lt;P&gt;I found my self using lots and lots of textblocks to display some information to the user. I was struggling with several limitations of textblocks: how they wrap depends on the container, databinding part of the text is not possible without databinding all of it, and there is no way to allow the user to select the text for copying to the clipboard. These limitations caused me to write lots of code to work around the issues and provide the user experience that I wanted. I had dozens of ValueConverters to format the bound data into the correct strings and even more code and XAML to get the text blocks to wrap appropriately.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;What?&lt;/U&gt;&lt;/STRONG&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;A colleague suggested that FlowDocuments might provide some answers, So dug into them and discovered a world of solutions to the problems that I faced. Flow Documents are kind of like HTML. In fact you can find lots of sites that compare the two if you search for it. Here are the features that drew me in and forced me to rewrite my entire interface to use FlowDocuments:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Selection and&amp;nbsp;copying to the clipboard support is natural and free.&lt;/LI&gt;
&lt;LI&gt;The memory foot print compared to all the controls that I was using before was a huge improvement and likewise the performance was better as well (although I didn't measure it).&lt;/LI&gt;
&lt;LI&gt;For displaying text there is nothing better. You can easily indent, bold, align, wrap, etc. &lt;/LI&gt;
&lt;LI&gt;Hyperlinks work properly only inside a FlowDocument.&lt;/LI&gt;
&lt;LI&gt;If you use a FlowDocumentScrollViewer to display your flow document (this is what I used), you get Scrolling, Find, Print, and Zoom capabilities.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;The&amp;nbsp;one downside is that like textblocks there is not a simple way to bind&amp;nbsp;data to the document. But for a read-only view of data, it&amp;nbsp;is perfect.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;When?&lt;/U&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Based on my experience with FlowDocument so far, I would recommend using them anytime the number of textblocks outnumber the other controls on your window. You can also embed a flow document within another container control like a Grid. But I wouldn't recommend that unless you really need it.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;U&gt;How?&lt;/U&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;I will write more posts on how I am using flowdocuments and the special things I have learned, but here is a quick synopsis of how I used them in this particular case:&lt;/P&gt;
&lt;P&gt;I replaced the TreeView that I had bound to my hierarchical data with a recursive method that added indented paragraphs to a section. After it's done, I simply add the section to the flowdocument. Indenting a paragraph is a little tricky, but that's a later post. Of course, the tree is no longer collapsible, but I didn't really need it to be anyway. The indentation was all I needed. I created my own value converters that could convert by data into paragraphs. That allowed my recursive function to be very generic.&lt;/P&gt;
&lt;P&gt;I used Figures to have a right justified column of numbers associated with some but not all of the paragraphs in my hierarchy. There's not much info about Figures so I will probably make that one of my first posts after this one.&lt;/P&gt;
&lt;P&gt;Paragraphs can have borders, so I used that fact to add some nice horizontal lines to the output that lined up the numbers on the right with there headers and grouped some of the paragraphs together.&lt;/P&gt;
&lt;P&gt;One of the last things I did was to add in a way for the&amp;nbsp;user to add additional text to certain areas. In one instance I added a button that simply created paragraphs for some objects in the hierarchy that are skipped by default. In other areas, I created my own kind of expander that has the look of a tree view item and adds additional paragraphs below itself. I called this last one an CollapsibleSection because I derived it from Section. I will definitely have a post on that one. &lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9287433" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jpricket/archive/tags/WPF/default.aspx">WPF</category></item><item><title>WPF - A Stretching TreeView</title><link>http://blogs.msdn.com/jpricket/archive/2008/08/05/wpf-a-stretching-treeview.aspx</link><pubDate>Tue, 05 Aug 2008 23:32:15 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8834891</guid><dc:creator>Jason Prickett</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/jpricket/comments/8834891.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jpricket/commentrss.aspx?PostID=8834891</wfw:commentRss><description>&lt;p&gt;&lt;strong&gt;What is a stretching treeView?&lt;/strong&gt; &lt;/p&gt;  &lt;p&gt;Recently, I found the need to have a TreeView in my WPF application that was only a few levels deep. I didn't want a horizontal scrollbar to appear and I wanted the long text nodes to wrap. So, I invented the StretchingTreeView control.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Why couldn't I do this with a normal WPF TreeView?&lt;/strong&gt; &lt;/p&gt;  &lt;p&gt;Well, you can, but you have to replace the ControlTemplate for all the TreeViewItems. That's either a lot of XAML or a lot of code.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;So, what exactly is the problem?&lt;/strong&gt; &lt;/p&gt;  &lt;p&gt;If you look at the default ControlTemplate for a TreeViewItem, you will see that it contains a grid with 3 columns. In the first column is the expander, in the second column is the Header of the TreeViewItem. And in the last column is nothing. The second column is set to a Width of Auto which means that it will size to its contents. The third column is set to a Width of Star which means it will grow and shrink with the width of the TreeView. No matter what you put in the Header of the TreeViewItem, it will never stretch to the right edge of the TreeView. And Since the Header column is set to Auto, it will never cause a TextBlock or anything else to wrap. Instead, if you turn off the horizontal scrollbar, your long text items simply get clipped at the right edge of the TreeView.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;So, what's the code to fix it?&lt;/strong&gt; &lt;/p&gt;  &lt;p&gt;Well it was actually very simple. Once I found out that you can control what kind of Controls a TreeView creates for its items. By subclassing TreeView and overriding the methods GetContainerForItemOverride and IsItemItsOwnContainerOverride, you can control what types are created for your tree. This is especially important if you are databinding your tree to some hierarchy of objects and can't just create TreeViewItems directly. In any case here is the code...&lt;/p&gt;  &lt;pre class="code"&gt;    &lt;span style="color: rgb(0,0,255)"&gt;class&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;StretchingTreeView&lt;/span&gt; : &lt;span style="color: rgb(43,145,175)"&gt;TreeView
&lt;/span&gt;    {
        &lt;span style="color: rgb(0,0,255)"&gt;protected&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;override&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;DependencyObject&lt;/span&gt; GetContainerForItemOverride()
        {
            &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;StretchingTreeViewItem&lt;/span&gt;();
        }

        &lt;span style="color: rgb(0,0,255)"&gt;protected&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;override&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;bool&lt;/span&gt; IsItemItsOwnContainerOverride(&lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt; item)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; item &lt;span style="color: rgb(0,0,255)"&gt;is&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;StretchingTreeViewItem&lt;/span&gt;;
        }
    }

    &lt;span style="color: rgb(0,0,255)"&gt;class&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;StretchingTreeViewItem&lt;/span&gt; : &lt;span style="color: rgb(43,145,175)"&gt;TreeViewItem
&lt;/span&gt;    {
        &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; StretchingTreeViewItem()
        {
            &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.Loaded += &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;RoutedEventHandler&lt;/span&gt;(StretchingTreeViewItem_Loaded);
        }

        &lt;span style="color: rgb(0,0,255)"&gt;private&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; StretchingTreeViewItem_Loaded(&lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt; sender, &lt;span style="color: rgb(43,145,175)"&gt;RoutedEventArgs&lt;/span&gt; e)
        {
            &lt;span style="color: rgb(0,128,0)"&gt;// The purpose of this code is to stretch the Header Content all the way accross the TreeView. 
&lt;/span&gt;            &lt;span style="color: rgb(0,0,255)"&gt;if&lt;/span&gt; (&lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.VisualChildrenCount &amp;gt; 0)
            {
                &lt;span style="color: rgb(43,145,175)"&gt;Grid&lt;/span&gt; grid = &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;.GetVisualChild(0) &lt;span style="color: rgb(0,0,255)"&gt;as&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;Grid&lt;/span&gt;;
                &lt;span style="color: rgb(0,0,255)"&gt;if&lt;/span&gt; (grid != &lt;span style="color: rgb(0,0,255)"&gt;null&lt;/span&gt; &amp;amp;&amp;amp; grid.ColumnDefinitions.Count == 3)
                {
                    &lt;span style="color: rgb(0,128,0)"&gt;// Remove the middle column which is set to Auto and let it get replaced with the 
&lt;/span&gt;                    &lt;span style="color: rgb(0,128,0)"&gt;// last column that is set to Star.
&lt;/span&gt;                    grid.ColumnDefinitions.RemoveAt(1);
                }
            }
        }

        &lt;span style="color: rgb(0,0,255)"&gt;protected&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;override&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;DependencyObject&lt;/span&gt; GetContainerForItemOverride()
        {
            &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;StretchingTreeViewItem&lt;/span&gt;();
        }

        &lt;span style="color: rgb(0,0,255)"&gt;protected&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;override&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;bool&lt;/span&gt; IsItemItsOwnContainerOverride(&lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt; item)
        {
            &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; item &lt;span style="color: rgb(0,0,255)"&gt;is&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;StretchingTreeViewItem&lt;/span&gt;;
        }
    }&lt;/pre&gt;

&lt;p&gt;Basically, all I do is create my own TreeViewItems that wait until they are loaded and then fix the Grid by removing the middle column. I don't like the fix, because it seems like a hack, but it's hardly any code. And that I like.&lt;/p&gt;

&lt;p&gt;I hope this helps somebody out there!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8834891" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jpricket/archive/tags/WPF/default.aspx">WPF</category></item><item><title>Exploring WPF - Programmatically scrolling a treeview</title><link>http://blogs.msdn.com/jpricket/archive/2007/11/05/exploring-wpf-programmatically-scrolling-a-treeview.aspx</link><pubDate>Tue, 06 Nov 2007 00:37:20 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5919520</guid><dc:creator>Jason Prickett</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/jpricket/comments/5919520.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jpricket/commentrss.aspx?PostID=5919520</wfw:commentRss><description>&lt;p&gt;Another one of the newest technologies released by Microsoft is WPF (Windows Presentation Foundation). This is a completely new way of thinking about User Interfaces. One of the things that I find the most interesting is the way that complex controls are created in WPF. Let's take a quick look at the TreeView control in WPF. &lt;/p&gt;  &lt;p&gt;If you are used to the Windows Forms TreeView, you should probably make a point to forget everything that you know about it. The WPF TreeView is really a composite of other elements (it is not a wrapper around the Win32 TreeView - for better or worse - I think better!). To get the look that you want for a control, WPF provides a Style for the control that is made up of the other simpler elements that give it the appropriate look. The TreeView is visually made up of a Border, then a ScrollViewer, and then an ItemsPresenter. So, I really haven't investigated what an ItemsPresenter is yet, but you should get the idea... the &amp;quot;control&amp;quot; is made up of other elements that deal with the drawing and the control is left to deal with the behavior.&lt;/p&gt;  &lt;p&gt;If you want to change the look of a TreeView, just change the style. You can change the border, remove the scroll viewer, or add any other elements you like. &lt;/p&gt;  &lt;p&gt;But the real reason I wanted to write this post was to share the code that I had to write to programmatically scroll the treeview. Why would I do that? Well, I was implementing Drag n Drop on this particular TreeView and needed to scroll for the user when they were dragging near the bottom or top of the tree. Because you can change the Style of the TreeView, there isn't a built in way to get to the scrollviewer which really stinks. But, knowing that my control wouldn't change, I was able to create a simple property on my subclasses TreeView to get the scroll viewer and here it is:&lt;/p&gt;  &lt;p&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; private ScrollViewer ScrollViewer   &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; {    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; get    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; {    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; if (m_scrollViewer == null)    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; {    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; DependencyObject border = VisualTreeHelper.GetChild(this, 0);    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; if (border != null)    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; {    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; m_scrollViewer = VisualTreeHelper.GetChild(border, 0) as ScrollViewer;    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; }    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; } &lt;/p&gt;  &lt;p&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; return m_scrollViewer;   &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; }    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; }&lt;/p&gt;  &lt;p&gt;As you can see, if you know your Visual tree, it is easy to get the ScrollViewer. Once I had the scrollviewer the logic to scroll the tree view was simple as well:&lt;/p&gt;  &lt;p&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; internal void ScrollIfNeeded(Point mouseLocation)   &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; {    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; if (this.ScrollViewer != null)    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; {    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; double scrollOffset = 0.0; &lt;/p&gt;  &lt;p&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; // See if we need to scroll down   &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; if (this.ScrollViewer.ViewportHeight - mouseLocation.Y &amp;lt; 20.0)    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; {    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; scrollOffset = 3.0;    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; }    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; else if (mouseLocation.Y &amp;lt; 20.0)    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; {    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; scrollOffset = -3.0;    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; } &lt;/p&gt;  &lt;p&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; // Scroll the tree down or up   &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; if (scrollOffset != 0.0)    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; {    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; scrollOffset += this.ScrollViewer.VerticalOffset; &lt;/p&gt;  &lt;p&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; if (scrollOffset &amp;lt; 0.0)   &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; {    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; scrollOffset = 0.0;    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; }    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; else if (scrollOffset &amp;gt; this.ScrollViewer.ScrollableHeight)    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; {    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; scrollOffset = this.ScrollViewer.ScrollableHeight;    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; } &lt;/p&gt;  &lt;p&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; this.ScrollViewer.ScrollToVerticalOffset(scrollOffset);   &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; }    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; }    &lt;br /&gt;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0;&amp;#xA0; }&lt;/p&gt;  &lt;p&gt;I won't go into a lot of explanation, but if the user is dragging the mouse 20 units (not pixels) from the top of the scroll area or 20 units from the bottom of the scroll area, I simple move the scroll area the appropriate direction by 3 units. &lt;/p&gt;  &lt;p&gt;I hope this post helps someone out there trying to do the same sort of thing!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5919520" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jpricket/archive/tags/WPF/default.aspx">WPF</category></item></channel></rss>