{"id":2067,"date":"2014-06-16T21:53:15","date_gmt":"2014-06-16T21:53:15","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=2067"},"modified":"2014-06-16T21:53:15","modified_gmt":"2014-06-16T21:53:15","slug":"creating-a-custom-panel-using-wpf","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/creating-a-custom-panel-using-wpf\/","title":{"rendered":"Creating a custom panel using WPF"},"content":{"rendered":"<p>The Grid, StackPanel, WrapPanel and DockPanel are used to layout controls in WPF. All four are derived from the WPF Panel class. So if we want to create our own &#8220;custom panel&#8221; we obviously use the Panel as our starting point.<\/p>\n<p>So to start with, we need to create a subclass of the Panel class in WPF. We then need to override both the <em>MeasureOverride<\/em> and <em>ArrangeOverride<\/em> methods.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic class MyCustomPanel : Panel\r\n{\r\n   protected override Size MeasureOverride(Size availableSize)\r\n   {\r\n      return base.MeasureOverride(availableSize);\r\n   }\r\n\r\n   protected override Size ArrangeOverride(Size finalSize)\r\n   {\r\n      return base.ArrangeOverride(finalSize);\r\n   }\r\n}\r\n<\/pre>\n<p>WPF implements a two pass layout system to both determine the sizes and positions of child elements within the panel.<\/p>\n<p>So the first phase of this process is to measure the child items and find what their desired size is, given the available size. <\/p>\n<p>It&#8217;s important to note that we need to call the child elements <em>Measure<\/em> method before we can interact with it&#8217;s <em>DesiredSize<\/em> property. For example<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nprotected override Size MeasureOverride(Size availableSize)\r\n{\r\n   Size size = new Size(0, 0);\r\n\r\n   foreach (UIElement child in Children)\r\n   {\r\n      child.Measure(availableSize);\r\n      resultSize.Width = Math.Max(size.Width, child.DesiredSize.Width);\r\n      resultSize.Height = Math.Max(size.Height, child.DesiredSize.Height);\r\n   }\r\n\r\n   size.Width = double.IsPositiveInfinity(availableSize.Width) ?\r\n      size.Width : availableSize.Width;\r\n\r\n   size.Height = double.IsPositiveInfinity(availableSize.Height) ? \r\n      size.Height : availableSize.Height;\r\n\r\n   return size;\r\n}\r\n<\/pre>\n<p><em>Note: We don&#8217;t want to return a infinite value from the available width\/height, instead we&#8217;ll return 0<\/em><\/p>\n<p>The next phase in this process is to handle the arrangement of the children using <em>ArrangeOverride<\/em>. For example<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nprotected override Size ArrangeOverride(Size finalSize)\r\n{\r\n   foreach (UIElement child in Children)\r\n   {\r\n      child.Arrange(new Rect(0, 0, child.DesiredSize.Width, child.DesiredSize.Height));\r\n   }\r\n   return finalSize;\r\n}\r\n<\/pre>\n<p>In the above, minimal code, we&#8217;re simply getting each child element&#8217;s desired size and arranging the child at point 0, 0 and giving the child it&#8217;s desired width and height. So nothing exciting there. However we could arrange the children in other, more interesting ways at this point, such as stacking them with an offset like a deck of cards or largest to smallest (or vice versa) or maybe recreate an existing layout but use transformation to animate their arrangement.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Grid, StackPanel, WrapPanel and DockPanel are used to layout controls in WPF. All four are derived from the WPF Panel class. So if we want to create our own &#8220;custom panel&#8221; we obviously use the Panel as our starting point. So to start with, we need to create a subclass of the Panel class [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[13],"tags":[],"class_list":["post-2067","post","type-post","status-publish","format-standard","hentry","category-wpf"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/2067","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=2067"}],"version-history":[{"count":10,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/2067\/revisions"}],"predecessor-version":[{"id":2089,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/2067\/revisions\/2089"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=2067"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=2067"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=2067"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}