Skip to content

Top 10 custom panels?

April 28, 2007

Note: http://robrelyea.com/wpf/panels will redirect you to this starter list and more polished lists in the future.

I’d love to know what subclasses of Panel (that we don’t ship with WPF) you find most interesting or helpful in your work?  At Mix07, I’d like to pass along pointers to the best ones out there…

My first example will be the TreeMapPanel that Kevin wrote and ships in his bag-o-tricks.

What are candidates for the top 10?

  • or just interesting ones you care to point out?
  • or one you wrote and published?
  • or one that you wrote and published as part of a larger application/sample?

 

Update: ok, so I did a bit of searching on the web and found the following to get this list started…

An unsorted list of Panels I’ve found, or others have suggested:

 

Book Content

  • WPF Unleashed, Adam Nathan, Chapter 17 – Layout with Custom Panels (builds an 2007 Office-Like RibbonPanel)
  • Applications = Code + Markup, Charles Petzold, Chapter 12 – Custom Panels, (builds several, including RadialPanel)
  • Programming Windows Presentation Foundation, Sells/Griffith, online

 

Other helpful info on building panels:

From → WPF

12 Comments
  1. Nick T permalink

    Wow…cornerstacker.  I\’d completely forgotten about that.  I think I barely knew wpf back then.There\’s some really good panels in this list!

  2. Jeremiah permalink

    I have started working on a panel recently.  It\’s actually based off Kevin\’s AnimatingTilePanel.  It allows for multiple drag/drop (with rubber band select) with multiple drop areas.  It\’s my first WPF control and I\’ve been trying my damnedest to make as much use of XAML (style, templates, binding) as possible, but I know I fall short in some areas.  It\’s nowhere close to finished, but it works and I thought I\’d share.
     

    http://67.93.59.181:9050/dragdrop.zip

  3. Josh permalink

    Rob,
     
    Thanks for putting this list together.  What a great idea!
     
    You might want to add the DragCanvas to the list: http://www.codeproject.com/WPF/DraggingElementsInCanvas.asp
     
    Thanks!

  4. John permalink

    Hi Rob,
     
    sorry I didn\’t find your post earlier. Here\’s the source code to the Lens Panel:
     
    using System;using System.Collections.Generic;using System.Text;using System.Windows;using System.Windows.Controls;using System.Windows.Controls.Primitives;using System.Windows.Data;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Imaging;using System.Windows.Shapes;
    namespace Swordfish.WinFX.Controls{ /// <summary> ///  /// </summary> public class LensUniformWrapPanel : UniformWrapPanel {  private Point lastPoint;
      private double radiusSquared = 40000;  private double radius = 200;  private double strength = 50;
      private bool mouseOver = false;
      public LensUniformWrapPanel()  {   this.MouseMove += new MouseEventHandler(LensUniformWrapPanel_MouseMove);   this.MouseEnter += new MouseEventHandler(LensUniformWrapPanel_MouseEnter);   this.MouseLeave += new MouseEventHandler(LensUniformWrapPanel_MouseLeave);  }
      protected Rect GetTransformedRect(Point location, Size size)  {   Vector Top = new Vector(location.X + size.Width * 0.5, location.Y);   Vector Bottom = new Vector(location.X + size.Width * 0.5, location.Y + size.Height);
       Vector Left = new Vector(location.X, location.Y + size.Height * 0.5);   Vector Right = new Vector(location.X + size.Width, location.Y + size.Height * 0.5);
       ApplyLensToPoint(ref Top);   ApplyLensToPoint(ref Bottom);   ApplyLensToPoint(ref Left);   ApplyLensToPoint(ref Right);
       Rect retVal = new Rect(new Point(Left.X, Top.Y), new Size(Right.X – Left.X, Bottom.Y – Top.Y));   return retVal;  }
      protected void ApplyLensToPoint(ref Vector point)  {   Vector centre = (Vector)lastPoint;   Vector diff = point – centre;   if (diff.LengthSquared < radiusSquared)   {    Vector normalized = diff;    normalized.Normalize();    Vector offset = normalized * Math.Pow(Math.Sin(diff.Length / radius * Math.PI), 1) * strength;    point += offset;    if ((point – centre).LengthSquared > radiusSquared)    {     point = centre + normalized * radius;    }   }  }
      protected override Size MeasureOverride(Size availableSize)  {   ScaleTransform unit = new ScaleTransform(1, 1);   // Get the maximum size   foreach (FrameworkElement child in InternalChildren)   {    child.LayoutTransform = unit;   }
       return base.MeasureOverride(availableSize);  }
      /// <summary>  /// Override the default Arrange method  /// </summary>  /// <param name="finalSize"></param>  /// <returns></returns>  protected override Size ArrangeOverride(Size finalSize)  {   if (!mouseOver)   {    return base.ArrangeOverride(finalSize);   }
       Size returnSize = new Size(    Math.Max(uniformSize.Width, finalSize.Width / columnCount),    Math.Max(uniformSize.Height, finalSize.Height / rowCount));
       Size renderedSize = new Size(Math.Round(uniformSize.Width), Math.Round(uniformSize.Height));
       int columnNo = 0;   int rowNo = 0;
       foreach (FrameworkElement child in InternalChildren)   {    Rect theRect = GetTransformedRect(new Point(Math.Round(columnNo * uniformSize.Width), Math.Round(rowNo * uniformSize.Height)), renderedSize);
        // Round off the rectangle sizes otherwise the PresentationFontCache gets thrashed    // from all the different font sizes.    ScaleTransform transform = new ScaleTransform(Math.Round(theRect.Width)/renderedSize.Width, Math.Round(theRect.Height)/renderedSize.Height);    child.LayoutTransform = transform;
        child.Arrange(theRect);
        switch (itemOrdering)    {     case Orientation.Vertical:      rowNo++;      if (rowNo >= rowCount)      {       rowNo = 0;       columnNo++;      }      break;     case Orientation.Horizontal:      columnNo++;      if (columnNo >= columnCount)      {       columnNo = 0;       rowNo++;      }      break;    }   }
       return new Size(returnSize.Width * columnCount, returnSize.Height * rowCount); // Returns the final Arranged size  }
      // ********************************************************************  // Mouse Handlers  // ********************************************************************  #region Mouse Handlers
      /// <summary>  /// When the mouse leaves, this restores the control to normal appearance  /// </summary>  /// <param name="sender"></param>  /// <param name="e"></param>  void LensUniformWrapPanel_MouseLeave(object sender, MouseEventArgs e)  {   mouseOver = false;   this.InvalidateMeasure();  }
      /// <summary>  /// When the mouse enters this indicates the lens effect is operational  /// </summary>  /// <param name="sender"></param>  /// <param name="e"></param>  void LensUniformWrapPanel_MouseEnter(object sender, MouseEventArgs e)  {   mouseOver = true;  }
      /// <summary>  /// Updates the appearance as the mouse moves over  /// </summary>  /// <param name="sender"></param>  /// <param name="e"></param>  void LensUniformWrapPanel_MouseMove(object sender, MouseEventArgs e)  {   lastPoint = Mouse.GetPosition(this);   this.InvalidateArrange();  }
      #endregion Mouse Handlers
     }}

  5. John permalink

    Missed out something on my last comment. You\’d probably find the code to the base class of my lens panel handy as well:
     
    namespace Swordfish.WinFX.Controls{ /// <summary> /// </summary> public class UniformWrapPanel : Panel {  // ********************************************************************  // Private Fields  // ********************************************************************  #region Private Fields
      /// <summary>  /// The size of the cells to draw in the panel  /// </summary>  protected Size uniformSize;  /// <summary>  /// number of columns  /// </summary>  protected int columnCount;  /// <summary>  /// number of rows  /// </summary>  protected int rowCount;  /// <summary>  /// item ordering direction  /// </summary>  protected Orientation itemOrdering = Orientation.Vertical;  /// <summary>  /// item position flow direction  /// </summary>  protected Orientation wrapMode = Orientation.Horizontal;
      #endregion
      // ********************************************************************  // Base Class Overrides  // ********************************************************************  #region Base Class Overrides
      /// <summary>  /// Override the default Measure method of Panel   /// </summary>  /// <param name="availableSize"></param>  /// <returns></returns>  protected override Size MeasureOverride(Size availableSize)  {   Size childSize = availableSize;   uniformSize = new Size(1, 1);
       // Get the maximum size   foreach (UIElement child in InternalChildren)   {    child.Measure(childSize);    uniformSize.Width = Math.Max(uniformSize.Width, child.DesiredSize.Width);    uniformSize.Height = Math.Max(uniformSize.Height, child.DesiredSize.Height);   }
       // Work out the size required depending if we are going to flow them down the left side, or across the top   switch (wrapMode)   {    case Orientation.Horizontal:     columnCount = (int)Math.Max(1, Math.Min(InternalChildren.Count, availableSize.Width / uniformSize.Width));     rowCount = (int)Math.Ceiling((double)InternalChildren.Count / (double)columnCount);     if (itemOrdering == Orientation.Vertical && rowCount!=0)      columnCount = (int)Math.Ceiling((double)InternalChildren.Count / (double)rowCount);     break;    case Orientation.Vertical:     rowCount = (int)Math.Max(1, Math.Min(InternalChildren.Count, availableSize.Height / uniformSize.Height));     columnCount = (int)Math.Ceiling((double)InternalChildren.Count / (double)rowCount);     if (itemOrdering == Orientation.Horizontal && columnCount!=0)      rowCount = (int)Math.Ceiling((double)InternalChildren.Count / (double)columnCount);     break;   }
       Size requestedSize = new Size(columnCount * uniformSize.Width, rowCount * uniformSize.Height);
       return requestedSize;  }
      /// <summary>  /// Override the default Arrange method  /// </summary>  /// <param name="finalSize"></param>  /// <returns></returns>  protected override Size ArrangeOverride(Size finalSize)  {   int columnNo = 0;   int rowNo = 0;
       Size returnSize = new Size(    Math.Max(uniformSize.Width, finalSize.Width / columnCount),    Math.Max(uniformSize.Height, finalSize.Height / rowCount));
       Size renderedSize = new Size(Math.Round(uniformSize.Width), Math.Round(uniformSize.Height));
       foreach (UIElement child in InternalChildren)   {    child.Arrange(new Rect(new Point(Math.Round(columnNo * uniformSize.Width), Math.Round(rowNo * uniformSize.Height)), renderedSize));
        switch (itemOrdering)    {     case Orientation.Vertical:      rowNo++;      if (rowNo >= rowCount)      {       rowNo = 0;       columnNo++;      }      break;     case Orientation.Horizontal:      columnNo++;      if (columnNo >= columnCount)      {       columnNo = 0;       rowNo++;      }      break;    }   }
       return new Size(returnSize.Width * columnCount, returnSize.Height * rowCount); // Returns the final Arranged size  }
      #endregion Base Class Overrides
      // ********************************************************************  // Properties  // ********************************************************************  #region Properties
      /// <summary>  /// Gets sets the orientation of the order that items appear  /// </summary>  public Orientation ItemOrdering  {   get   {    return itemOrdering;   }   set   {    itemOrdering = value;    InvalidateMeasure();   }  }
      /// <summary>  /// Gets/Sets the method of flowing the layout of the items  /// </summary>  public Orientation WrapMode  {   get   {    return wrapMode;   }   set   {    wrapMode = value;    InvalidateMeasure();   }  }
      #endregion Properties }}

  6. Pavan permalink

    Hey Rob,      You can include my ElementFlow control too…its now a Panel ;) http://pavanpodila.spaces.live.com/blog/cns!9C9E888164859398!468.entry

  7. Unknown permalink

    junexx16 junexx01 wow gold wow gold wow gold wow gold wow gold 全教振 全教振 韩国签证 德国签证 新西兰签证 爱尔兰留学签证 擦鞋机 擦鞋店加盟 黑马股 黑马股 大智慧 大智慧 深圳网页设计 深圳网页设计 FAG轴承 FAG轴承 NSK轴承 NSK轴承 中高年 転職 中高年 転職 毛穴 黒ずみ 毛穴 黒ずみ wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold

  8. Unknown permalink

    kh15wt gtk06y wow gold wow gold wow gold wow gold 全教振 中高年 転職 大智慧 FX 进口轴承 美国签证 NSK轴承 TIMKEN轴承 法国签证 全教振 全教振 炒股软件 炒股软件 大智慧 深圳网页制作 深圳网页制作 进口轴承 NSK轴承 水洗厂 干洗设备 朗阁培训 英国签证 中高年 転職 FX 黑马股 毛穴 黒ずみ 毛穴 黒ずみ TIMKEN轴承 出会い系 コスメ コスメ wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold

  9. Unknown permalink

    jg30mh gtg07y wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold 泵 泵 泵 泵 水泵 水泵 水泵 水泵 水泵 齿轮输油泵 齿轮输油泵 环保设备 环保设备 China Travel China Tours China Tours beijing Tours beijing Tours beijing Travel beijing Travel shanghai Tours shanghai Tours shanghai Travel shanghai Travel wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold wow gold 水泵 水泵 水泵

  10. Unknown permalink

    アーネスト  設計事務所 行政書士  アクサ アクサダイレクト     三井ダイレクト 有料老人ホーム  現金化   クレジットカード 現金化    ドロップシッピング  医院開業   ショッピング枠 現金化 為替     看護  ウェディング  結婚式   ウェディング 結婚式 沖縄旅行 クレジットカード 現金化  外国為替  引越  副業  賃貸  不動産 競馬予想 出会い系

  11. Unknown permalink

    Welcome to enter (wow gold) and (wow power leveling) trading site, (wow gold) are cheap, (wow power leveling) credibility Very good! Quickly into the next single! Key words directly to the website click on transactions! -144478220826189

  12. Might want to add CardPanel to the list. It arranges the children in a stack like a deck of cards. http://www.jarloo.com/cardpanel-a-custom-wpf-panel/

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: