{"id":2273,"date":"2010-03-22T23:00:00","date_gmt":"2010-03-22T23:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/visualstudio\/2010\/03\/22\/wpf-in-visual-studio-2010-part-5-window-management\/"},"modified":"2022-10-14T13:02:02","modified_gmt":"2022-10-14T20:02:02","slug":"wpf-in-visual-studio-2010-part-5-window-management","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/visualstudio\/wpf-in-visual-studio-2010-part-5-window-management\/","title":{"rendered":"WPF in Visual Studio 2010 &#8211; Part 5 : Window Management"},"content":{"rendered":"<p><span style=\"color: #008080;\">This is the fifth article in the <\/span><a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wpf-in-visual-studio-2010-part-1-introduction\/\"><span style=\"color: #008080;\">WPF in Visual Studio 2010 series<\/span><\/a><span style=\"color: #008080;\">. This week, guest author <\/span><span style=\"color: #008080;\">Matthew Johnson<\/span><span style=\"color: #008080;\"> presents a fascinating <\/span><span style=\"color: #008080;\">behind-the-scenes<\/span><span style=\"color: #008080;\"> look at Visual Studio&#8217;s innovative window management system. <em>&#8211; Paul Harrington<\/em><\/span><\/p>\n<h4>Background<\/h4>\n<p>Several people have expressed interest in how much effort was required to write a WPF window management system that supports docking and undocking windows, reordering tabs, and persisting layout.\u00a0 The answer: we were able to use lots of WPF fundamentals, but wrote many custom controls.\u00a0 I\u2019ll walk through some of the major features of the WPF window management system and explain how we implemented what we did.<\/p>\n<p>One thing to keep in mind while reading this article is that a version of the Visual Studio window layout system is also used by the <a href=\"http:\/\/www.microsoft.com\/expression\/\">Expression 3<\/a> products (Expression Blend, Expression Web, Expression Design).\u00a0 Of course, Expression heavily customized the look-and-feel, but the underlying implementation and features are shared.<\/p>\n<h4>Layout<\/h4>\n<p>One of the first areas we tackled when designing the windowing system was how layout would work.\u00a0 Layout has two main underpinnings:<\/p>\n<ul>\n<li>Measurement and arrangement of windows<\/li>\n<li>Persistence of layout across multiple sessions<\/li>\n<\/ul>\n<h5>Data model and persistence<\/h5>\n<p>Practicing data and UI separation was the easiest way for us to decouple the visual appearance of the windowing system from the persistent layout data.\u00a0 Non-leaf elements contain information about the relative location and size of splitters, tab groups, document groups, and floating windows.\u00a0 The leaf elements are placeholders for tool windows and documents.\u00a0 In the layout tree, the only information stored has to do with sizes, positions, and monikers which uniquely identify a tool window or document.<\/p>\n<p>To persist this data, we initially planned to use the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.xaml.xamlservices%28VS.100%29.aspx\">XamlServices<\/a> class to read and write the data model as XAML.\u00a0 However, general-purpose XAML reading and writing inherently relies on reflection to gather information about types.\u00a0 Since reading window layouts is on Visual Studio\u2019s startup path, our performance testing found that this was adding dozens of milliseconds per window layout (and for Visual Studio, dozens of milliseconds adds up quickly).\u00a0 To squeeze out more performance, we wrote a serializer generator that understands our specific object schema, which is faster since the \u201ctype understanding\u201d happened at code generation time, not at runtime.\u00a0 This gives additional security benefits for us as well, since our parser will only instantiate known objects (using the general-purpose XamlServices would have allowed any object to be instantiated at startup without our direct knowledge, if the persisted window layout were modified).<\/p>\n<h5>Control model<\/h5>\n<p>The layout data tree is converted into actual controls using WPF\u2019s <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms742521.aspx\">DataTemplates<\/a>.\u00a0 Visual Studio keeps a separate DataTemplate for each data model type in its <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.windows.application.aspx\">Application<\/a>\u2019s <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.windows.resourcedictionary.aspx\">ResourceDictionary<\/a>.\u00a0 There is one caveat here: top-level windows (like Visual Studio\u2019s floating documents and tool windows) can\u2019t easily be built from DataTemplates directly.\u00a0 Instead, these root layout elements are constructed directly by a special control factory.\u00a0 After those are constructed, each other data model element is built into a control simply by being placed in a ContentControl or ItemsControl.<\/p>\n<p>For styling our controls, we use WPF\u2019s generic <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa358533(VS.100).aspx\">theme<\/a> dictionaries extensively.\u00a0 Every control in the logical tree (the controls built from DataTemplates) are subclasses of a WPF base class, and override the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.windows.frameworkelement.defaultstylekey(VS.100).aspx\">DefaultStyleKeyProperty<\/a>.\u00a0 We then provide our base styles in the generic theme dictionary.\u00a0 Custom style overrides can be placed in the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.windows.application.resources(VS.100).aspx\">Application\u2019s ResourceDictionary<\/a>, which has a higher priority than the generic theme dictionary.\u00a0 In fact, we use style overrides for Visual Studio itself\u2014anything that is Visual Studio-specific (such as referencing colors from Visual Studio\u2019s color table) is kept out of the sharable code.\u00a0 The \u201cStyles, DataTemplates, and Implicit Keys\u201d section of the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms750613.aspx\">Resources Overview<\/a> and <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms752339.aspx\">Guidelines for Designing Stylable Controls<\/a> article explain this approach in more detail.<\/p>\n<p>This diagram summarizes the different parts involved in turning layout data into a complete visual tree for Visual Studio.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/LayoutDataStructure_4.png\"><img decoding=\"async\" title=\"LayoutDataStructure\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/03\/LayoutDataStructure_thumb_1.png\" alt=\"LayoutDataStructure\" width=\"187\" height=\"582\" border=\"0\" \/><\/a><\/p>\n<p>We were able to use many standard WPF controls as part of the layout of the windowing system.\u00a0 For example, we a derivation of the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.windows.controls.tabcontrol.aspx\">TabControl<\/a> for tab groups.\u00a0 However, we did invest a lot into custom controls to add functionality beyond what exists in WPF itself.\u00a0 Some of these are described in the deep dives below.<\/p>\n<h4>Docking and undocking windows<\/h4>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/DockAdornments_2.png\"><img decoding=\"async\" title=\"DockAdornments\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/03\/DockAdornments_thumb.png\" alt=\"DockAdornments\" width=\"725\" height=\"657\" border=\"0\" \/><\/a><\/p>\n<p>The docking system is what allows users to tear off tool windows or documents and re-arrange their positions.\u00a0 When I say \u201cdock adornment\u201d, I\u2019m specifically referring to the directional semi-transparent tiles that appear when you start to drag a floating window.\u00a0 Preview shadows (the blue semi-transparent rectangle in the screenshot) give an indication of the position a floating window will have once you release it over a specific dock adornment.<\/p>\n<p>To understand how docking works, it\u2019s helpful to understand specifically the data model for the main window looks.\u00a0 For the above screenshot, the data model tree for the main window looks something like this:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/MainWindowStructure_8.png\"><img decoding=\"async\" title=\"MainWindowStructure\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/03\/MainWindowStructure_thumb_3.png\" alt=\"MainWindowStructure\" width=\"772\" height=\"566\" border=\"0\" \/><\/a><\/p>\n<p>When each of these data model elements are translated into the WPF visual tree (via DataTemplates and ControlTemplates), a custom control we created called DockTarget is inserted into places above which a dock adornment should show.\u00a0 For example, each TabGroup becomes a TabGroupControl in the visual tree, and TabGroupControl\u2019s ControlTemplate inserts a DockTarget around the content space.\u00a0 There is also a DockTarget for the title, and a DockTarget around each tab.<\/p>\n<p>Some DockTargets indicate that an adornment should be shown (like the DockTarget around the content space).\u00a0 Other DockTargets (like the one around each tab and the one around the title bar) don\u2019t request an adornment, but still provide a preview shadow.<\/p>\n<table style=\"width: 600px;\" border=\"0\" cellspacing=\"0\" cellpadding=\"2\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"200\"><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/HeaderDockTarget_2.png\"><img decoding=\"async\" title=\"HeaderDockTarget\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/03\/HeaderDockTarget_thumb.png\" alt=\"HeaderDockTarget\" width=\"240\" height=\"189\" border=\"0\" \/><\/a><\/td>\n<td valign=\"top\" width=\"200\"><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/CenterDockTarget_2.png\"><img decoding=\"async\" title=\"CenterDockTarget\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/03\/CenterDockTarget_thumb.png\" alt=\"CenterDockTarget\" width=\"240\" height=\"239\" border=\"0\" \/><\/a><\/td>\n<td valign=\"top\" width=\"200\"><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/TabDockTarget_2.png\"><img decoding=\"async\" title=\"TabDockTarget\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/03\/TabDockTarget_thumb.png\" alt=\"TabDockTarget\" width=\"194\" height=\"240\" border=\"0\" \/><\/a><\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"200\">\n<p align=\"center\">Header DockTarget<\/p>\n<\/td>\n<td valign=\"top\" width=\"200\">\n<p align=\"center\">Center DockTarget<\/p>\n<\/td>\n<td valign=\"top\" width=\"200\">\n<p align=\"center\">Tab DockTarget<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>DockTargets serve both as a marker for where to show dock adornments and previews, but also as the controller for what kind of docking action occurs when you drop a window over that target or the adornment it produces.\u00a0 While dragging a floating window, each mouse-move causes our dock manager to perform a <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms752097(VS.100).aspx\">hit test<\/a> using WPF\u2019s hit testing system (actually, a hit test is performed on the window on the element in the set of all (main window + floating windows) which is found to be under the mouse and on top of the z-order).\u00a0 The DockManager then walks up the visual tree and enumerates all of the DockTargets in the ancestry of the hit element.\u00a0 The DockManager uses these DockTargets to reposition dock adornments and the dock preview window accordingly.\u00a0 In this way, we can make changes to when and how dock adornments and preview appear simply by changing the ControlTemplates for controls in the main window.<\/p>\n<p>For the dock adornment and dock preview windows themselves, we use a top-level <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.windows.interop.hwndsource.aspx\">HwndSource<\/a> to present the visual appearance.\u00a0 Although the term \u201cadornment\u201d is shared with a WPF concept, we could not use WPF\u2019s <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.windows.documents.adornerlayer(VS.100).aspx\">adorner layer<\/a> primarily because we want the adornment and preview to be on top of two different top-level windows: the floating window being dragged and the target window.\u00a0 The only way to accomplish this is with a third top-level window (you would be surprised how much more confusing dock adornments and previews would be if their content was covered up by the window being docked).<\/p>\n<h4>Auto-hide overlays<\/h4>\n<p>In Visual Studio, auto-hidden windows can be shown in a flyout form, which overlaps other docked windows.\u00a0 These windows are part of the main window frame, and the auto-hide flyout is a sibling of each docked window.\u00a0 In previous versions of Visual Studio, every tool window or document was represented by an HWND.\u00a0 The auto-hide flyout HWND was simply kept always above the other HWNDs in z-order, and that kept its child subtree above other windows.<\/p>\n<p>WPF <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa970688(VS.100).aspx\">airspace<\/a> limitations effectively boil down to this rule: If you are a WPF surface presented in an HWND (an HwndSource or System.Windows.Window), your HWND has a single presentation surface for WPF content, and that single presentation surface is always <strong>below<\/strong> every child HWND.\u00a0 In the screenshot below, the Windows Forms designer and the Windows Forms Properties tool window are both HWND-based documents (highlighted in <span style=\"color: #008000;\">green<\/span>), and consequently always render above the WPF main window.\u00a0 The auto-hidden Output window, however, is entirely WPF (highlighted in <span style=\"color: #ff0000;\">red<\/span>).<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/HwndOverlapGreen_2.png\"><img decoding=\"async\" title=\"HwndOverlapGreen\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/03\/HwndOverlapGreen_thumb.png\" alt=\"HwndOverlapGreen\" width=\"767\" height=\"696\" border=\"0\" \/><\/a><\/p>\n<p>To achieve overlap here, we had to wrap every auto-hidden flyout in its own HWND.\u00a0 This is implemented with an HwndHost (which puts the HWND into the main window\u2019s visual tree) that contains an HwndSource (which allows WPF content to be presented in a new child HWND).<\/p>\n<p>This sounds simple enough, but there were some additional issues we had to overcome:<\/p>\n<ol>\n<li>Each HWND which is a direct child of the main window has to have both <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms632600(VS.85).aspx\">WS_CLIPSIBLINGS<\/a> and WS_CLIPCHILDREN applied as Windows styles.\u00a0 Without these styles, Windows will allow either window to overdraw its own siblings if their surfaces interesect.<\/li>\n<li>Many actions (such as acquiring focus) can change the z-order of an HWND.\u00a0 For example, if the Solution Explorer is auto-hidden and overlaps the docked Properties window, clicking on the \u201cProperties\u201d toolbar button can focus and activate the Properties window while leaving the Solution Explorer shown on top of it.\u00a0 The Properties window would normally come to the front of the z-order and overlap the Solution Explorer.\u00a0 To handle this case, we have <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms632652(VS.85).aspx\">WM_WINDOWPOSCHANGED<\/a> handlers on each of the root sibling windows.\u00a0 When anything that\u2019s not the auto-hide HWND has its z-order change, we make sure the auto-hide HWND is brought to the front again to compensate.<\/li>\n<li>WPF passes <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms753197.aspx\">inherited properties<\/a> through the logical tree.\u00a0 By using a child HwndSource, we effectively created a new logical tree that\u2019s separate from the main window.\u00a0 For example, this prevents the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.windows.media.textoptions.textformattingmode%28VS.100%29.aspx\">TextOptions.TextFormattingMode<\/a> property we set on the main window to improve text clarity from inheriting to the auto-hide flyout.\u00a0 However, this can be overcome!\u00a0 Our HwndHost (which is an element in the main window\u2019s logical tree) uses <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.windows.frameworkelement.addlogicalchild(VS.100).aspx\">AddLogicalChild<\/a> to add the root visual of the HwndSource to the main window\u2019s logical tree.\u00a0 This allows inherited properties and resource lookup to flow naturally from the main window to the auto-hide flyout as if there were no HWND.<\/li>\n<\/ol>\n<h4>Custom window chrome<\/h4>\n<p>If you\u2019ve floated any tool windows or documents, you\u2019ve probably noticed that these windows have non-standard title bars and resize areas.\u00a0 However, the window frame and titlebar is entirely WPF\u2014how were we able to achieve that look while still supporting new Windows 7 features like <a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/tips-and-tricks-window-management-aero-snapping\/\">Aero Snap<\/a>?<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/FloatingToolWindow_2.png\"><img decoding=\"async\" title=\"FloatingToolWindow\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/03\/FloatingToolWindow_thumb.png\" alt=\"FloatingToolWindow\" width=\"287\" height=\"323\" border=\"0\" \/><\/a><\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/4\/2019\/06\/FloatingDocument_2.png\"><img decoding=\"async\" title=\"FloatingDocument\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/03\/FloatingDocument_thumb.png\" alt=\"FloatingDocument\" width=\"547\" height=\"430\" border=\"0\" \/><\/a><\/p>\n<p>Our implementation was mostly handled using techniques from Joe Castro\u2019s <a href=\"https:\/\/learn.microsoft.com\/en-us\/archive\/blogs\/wpfsdk\/\">WPF Chrome<\/a> project.\u00a0 In short, WPF Chrome works by handling several Windows messages (WM_NCCALCSIZE, WM_NCHITTEST, and others) to inform Windows that Visual Studio is drawing the entire non-client area, but that Windows should treat certain areas as non-client for hit-testing purposes.\u00a0 In this way, we did not have to implement any functionality specific to the moving, sizing, maximizing, or restoring of the window.<\/p>\n<p>Beyond what exists in the WPF chrome sample, we only ended up needing to make a few changes to have operations work for owned windows (i.e. top-level windows that have their z-order and taskbar status tied to their owner window, the Visual Studio main window).<\/p>\n<ul>\n<li>When minimizing the Visual Studio main window, we explicitly minimize every floating window.\u00a0 Then, when the main window is restored, we restore each floating window to its previous state.\u00a0 The state transition is important in order to maintain the \u201csemi-maximized\u201d state of the window.\u00a0 Semi-maximized states are special states that Window maintains, such as \u201cdocked to one half of the monitor\u201d (done with Win+Left\/Win+Right or dragging to the monitor edge) or \u201cexpanded to fill the height of the monitor\u201d (done by dragging the top or bottom resize grip to the top or bottom of the monitor, or double-clicking on the top or bottom resize grips).\u00a0\u00a0 Without this state transition logic, the owned floating windows would restore to a non-semi-maximized state.<\/li>\n<li>When dragging to move or resize a window, Windows enters a move\/size loop during which normal mouse messages aren\u2019t dispatched (see <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms632622%28VS.85%29.aspx\">WM_ENTERSIZEMOVE<\/a>\/<a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms632623%28VS.85%29.aspx\">WM_EXITSIZEMOVE<\/a>\/<a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms632632%28VS.85%29.aspx\">WM_MOVING<\/a>).\u00a0 During the move-size loop, Visual Studio needs to be updating the dock adornments and previews mentioned above, so we handle these messages.\u00a0 This gives the added benefit that you can dock a floating window using the keyboard entirely.\u00a0 Alt+Space will show the system menu, and the Move option will enter the move-size loop.\u00a0 Once in the move-size loop, you can use the arrow keys to move the window over a dock adornment, press Enter, and dock the window without ever touching the mouse.<\/li>\n<\/ul>\n<h4>Arranging and reordering tabs<\/h4>\n<p>By default, WPF\u2019s TabControl uses a layout panel called <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.windows.controls.primitives.tabpanel(VS.100).aspx\">TabPanel<\/a>.\u00a0 However, TabControl and TabPanel has several shortcomings that we needed to add additional support for.<\/p>\n<ul>\n<li>TabPanel\u2019s implementation will always wrap tabs into multiple rows or columns once the tabstrip overflows.\u00a0 Visual Studio has traditionally displayed only a single row of tabs.<\/li>\n<li>TabControl doesn\u2019t directly allow for items which are in the tab control not to have tab representations.\u00a0 By default, when the document well overflows, Visual Studio removes tabs that would overflow.\u00a0 When the tool window tabstrip overflows, the tabs themselves are truncated, and the text uses ellipses.<\/li>\n<li>There isn\u2019t any out-of-the-box functionality for user-reordering of tabs.<\/li>\n<\/ul>\n<p>In order to add these features, we wrote custom Panel subclasses called for dealing with resizing, single-row layout, and tab hiding.<\/p>\n<p>The reordering logic is perhaps the most interesting.\u00a0 To summarize: when you start to drag tab, we capture the bounds of all of the tabs in the containing Panel.\u00a0 As you drag the tab, we detect whether or not the mouse has moved past the edge of the current tab in either direction.\u00a0 When it does, it swaps the data model order of those tabs (as well as the ordering of the bounds in the list of tab bounds).\u00a0 One tricky area: when the data model is swapped, WPF rebuilds the visual tree, and the UIElement that had captured the mouse for the drag operation is removed and a new control is built from template expansion.\u00a0 To continue the drag when the new element is created, we check in its OnInitialized override and see if the mouse left button is still pressed, and if our DockManager component still reports that a tab is being dragged.\u00a0 If so, we capture the mouse and resume the dragging operation for the new tab UIElement.<\/p>\n<p>One lesson we learned from our Panel subclass is that over-measuring text can be expensive.\u00a0 Our initial implementation would always pass the Panel\u2019s width to Measure on each child item (which is a finite value).\u00a0 However, we discovered that passing Double.PositiveInfinity for the width allowed WPF to optimize text measurement.\u00a0 Only if we detect that the text should be truncated (because of lack of space) do we calculate a finite value and then re-measure the truncated children.<\/p>\n<p><img decoding=\"async\" title=\"Matt\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/03\/5-Matt_3287b955-5e52-484b-8bce-a5d3232276b9.png\" alt=\"Matt\" width=\"108\" height=\"108\" align=\"left\" border=\"0\" \/><strong>Matthew Johnson<\/strong> \u2013 Developer, Visual Studio Platform\n<strong>Short Bio<\/strong>:\u00a0 Matthew has been at Microsoft for three years and on the Visual Studio Platform for two years.\u00a0 He works on WPF-related features of the Visual Studio window layout system.<\/p>\n<h4><\/h4>\n<h4><\/h4>\n<h3>Thanks<\/h3>\n<p><span style=\"color: #008080;\">Many thanks to Matt for this incredibly informative article. We\u2019d love to hear your feedback on this or any of the other articles in the series. Feel free to use the comment stream below. For next time, I\u2019ve asked another guest writer and software tester extraordinaire, Phil Price, to give his perspective on <a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wpf-in-visual-studio-2010-part-6-automated-ui-testing\/\">what it took to test Visual Studio 2010\u2019s new WPF look<\/a>. <\/span><span style=\"color: #008080;\"><em>&#8211; Paul Harrington<\/em><\/span><\/p>\n<p>Previous posts in the series:<\/p>\n<ul>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wpf-in-visual-studio-2010-part-1-introduction\/\">Part 1 : Introduction<\/a><\/li>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wpf-in-visual-studio-2010-part-2-performance-tuning\/\">Part 2 : Performance<\/a><\/li>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wpf-in-visual-studio-2010-part-3-focus-and-activation\/\">Part 3 : Focus and Activation<\/a><\/li>\n<li><a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wpf-in-visual-studio-2010-part-4-direct-hosting-of-wpf-content\/\">Part 4 : Direct Hosting of WPF content<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>This is the fifth article in the WPF in Visual Studio 2010 series. This week, guest author Matthew Johnson presents a fascinating behind-the-scenes look at Visual Studio&#8217;s innovative window management system. &#8211; Paul Harrington Background Several people have expressed interest in how much effort was required to write a WPF window management system that supports [&hellip;]<\/p>\n","protected":false},"author":13,"featured_media":255385,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[155],"tags":[20,133],"class_list":["post-2273","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-visual-studio","tag-wpf","tag-xaml"],"acf":[],"blog_post_summary":"<p>This is the fifth article in the WPF in Visual Studio 2010 series. This week, guest author Matthew Johnson presents a fascinating behind-the-scenes look at Visual Studio&#8217;s innovative window management system. &#8211; Paul Harrington Background Several people have expressed interest in how much effort was required to write a WPF window management system that supports [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/posts\/2273","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/users\/13"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/comments?post=2273"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/posts\/2273\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/media\/255385"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/media?parent=2273"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/categories?post=2273"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/tags?post=2273"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}