2012-05-18 5 views
2

У меня есть UserControl и этот UserControl должен быть изменен с использованием соотношения сторон. Это означает: ширина: высота = 2: 1. В настоящее время я использую этот код:WPF Resize UserControl с соотношением сторон

protected override Size ArrangeOverride(Size arrangeBounds) 
    { 
     if (ActualWidth == 0 || ActualHeight == 0) return arrangeBounds; 
     base.ArrangeOverride(arrangeBounds); 
     double ratio = 2; 

     if (Parent != null) 
     { 
      var size = new Size(arrangeBounds.Height * ratio, arrangeBounds.Height); 

      double containerWidth = ((FrameworkElement)Parent).ActualWidth; 
      if (containerWidth < size.Width) 
      { 
       double newHeight = arrangeBounds.Height * (containerWidth/size.Width); 
       canvas.Width = newHeight * ratio; 
       canvas.Height = newHeight; 
      } 
      else 
      { 
       canvas.Width = size.Height * ratio; 
       canvas.Height = size.Height; 
      } 
     } 

     return arrangeBounds; 
    } 

Но это на самом деле не работает. Это означает, что он работает, но не каждый раз. Если я макс. в окне он иногда не изменяется, поэтому его бит «случайный», если элемент управления будет изменен. Поэтому, если бы у кого-то было бы лучшее решение, если бы было очень приятно.

ответ

4

Это немного поздно, но я недавно наткнулся на такую ​​же проблему, и с тех пор я не нашел хорошее решение, которое я решил написать свой собственный макет управления/декоратор и написал сообщение в блоге об этом здесь:

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

В основном мое решение состояло в том, чтобы перезаписать как MeasureOverride, так и ArrangeOverride. Пока это работает очень хорошо во всех обычных контейнерах, и я не сталкивался с такими проблемами, как вы описали.

Я рекомендую прочитать пост, где вы найдете контроль рабочего декоратора, но наиболее важные методы таковы:

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); 
    } 

Я надеюсь, что это помогает кто-то!

4

Наиболее простым решением было бы привязать высоту непосредственно к ширине через преобразователь значений.

+0

Основная проблема заключается в том, что высота может стать слишком большой. Потому что, если ширина контейнера составляет 3000 пикселей, а высота 600 пикселей i будет масштабировать высоту до 1500 пикселей. Так что это будет tooooooo большой. –

+0

Условные обозначения можно обрабатывать в конвертере ... – EtherDragon