WPF Resize UserControl with aspect ratio

跟風遠走 提交于 2019-11-29 16:08:46

It's a bit late, but I recently came across the same problem and since I did not find a good solution I decided to write my own layout control/decorator and wrote a blog post about it here:

http://coding4life.wordpress.com/2012/10/15/wpf-resize-maintain-aspect-ratio/

Basically my solution was to overwrite both MeasureOverride and ArrangeOverride. So far it works very nicely in all of the common containers and I didn't encounter any problems like you described.

I recommend reading the post, where you find a working decorator control, but the most important methods are these:

   protected override Size MeasureOverride(Size constraint)
   {
      if (Child != null)
      {
         constraint = SizeToRatio(constraint, false);
         Child.Measure(constraint);

         if(double.IsInfinity(constraint.Width)
            || double.IsInfinity(constraint.Height))
         {
            return SizeToRatio(Child.DesiredSize, true);
         }

         return constraint;
      }

      // we don't have a child, so we don't need any space
      return new Size(0, 0);
   }

   protected override Size ArrangeOverride(Size arrangeSize)
   {
      if (Child != null)
      {
         var newSize = SizeToRatio(arrangeSize, false);

         double widthDelta = arrangeSize.Width - newSize.Width;
         double heightDelta = arrangeSize.Height - newSize.Height;

         double top = 0;
         double left = 0;

         if (!double.IsNaN(widthDelta)
            && !double.IsInfinity(widthDelta))
         {
            left = widthDelta/2;
         }

         if (!double.IsNaN(heightDelta)
            && !double.IsInfinity(heightDelta))
         {
            top = heightDelta/2;
         }

         var finalRect = new Rect(new Point(left, top), newSize);
         Child.Arrange(finalRect);
      }

      return arrangeSize;
   }

   public Size SizeToRatio(Size size, bool expand)
   {
      double ratio = AspectRatio;

      double height = size.Width / ratio;
      double width = size.Height * ratio;

      if (expand)
      {
         width = Math.Max(width, size.Width);
         height = Math.Max(height, size.Height);
      }
      else
      {
         width = Math.Min(width, size.Width);
         height = Math.Min(height, size.Height);
      }

      return new Size(width, height);
   }

I hope it helps someone!

EtherDragon

The most straightforward solution would be to Bind the Height directly to the Width, through a value converter.

Wrap your Control with a ViewBox and set the ViewBox.Stretch to Uniform. You can also restrict on MaxWidth and MaxHeight that way.

More Info on the Stretch-Enumeration @ MSDN

How to apply Stretch @ MSDN

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!