Создание шкалы Viewbox по вертикали, но растяжение по горизонтали

Я хочу создать Viewbox (или нечто подобное), которое масштабирует только его высоту, а затем растягивает его содержимое по горизонтали.

Если я это сделаю:

      

то я получаю это:

http://sofru.miximages.com/wpf/viewbox-center.png

Он действует так, как будто обе кнопки имеют HorizontalAlignment = «Центр», а затем масштабирует результат. Но я не хочу, чтобы HorizontalAlignment = «Центр»; Я хочу HorizontalAlignment = “Stretch”, вот так:

http://sofru.miximages.com/wpf/viewbox-stretch.png

Поэтому я хочу, чтобы он считывал нужную высоту своего содержимого, вычислял коэффициент масштабирования, основанный только на высоте, а затем позволял масштабируемому контенту растягиваться горизонтально.

Есть ли способ сделать это с помощью windows «Просмотр» и / или сторонней панели?

Нет такого контроля с WPF, но вы можете написать его самостоятельно без особых проблем. Вот пользовательский ViewboxPanel, который имеет ваши характеристики:

 public class ViewboxPanel : Panel { private double scale; protected override Size MeasureOverride(Size availableSize) { double height = 0; Size unlimitedSize = new Size(double.PositiveInfinity, double.PositiveInfinity); foreach (UIElement child in Children) { child.Measure(unlimitedSize); height += child.DesiredSize.Height; } scale = availableSize.Height / height; return availableSize; } protected override Size ArrangeOverride(Size finalSize) { Transform scaleTransform = new ScaleTransform(scale, scale); double height = 0; foreach (UIElement child in Children) { child.RenderTransform = scaleTransform; child.Arrange(new Rect(new Point(0, scale * height), new Size(finalSize.Width / scale, child.DesiredSize.Height))); height += child.DesiredSize.Height; } return finalSize; } } 

и вы используете его вот так:

     

Это определенно нуждается в некоторой работе, но это может заставить вас начать.

Для правильной работы ширины:

 protected override Size MeasureOverride(Size availableSize) { double height = 0; Size unlimitedSize = new Size(double.PositiveInfinity, double.PositiveInfinity); foreach (UIElement child in Children) { child.Measure(unlimitedSize); height += child.DesiredSize.Height; } scale = availableSize.Height / height; foreach (UIElement child in Children) { unlimitedSize.Width = availableSize.Width / scale; child.Measure(unlimitedSize); } return availableSize; } 

Я уверен, что ответ «нелегко».

Вот идея, которая, похоже, работает, но это неловко:

  1. Бросьте свой StackPanel в UserControl ( UserControl1 в примере ниже).

  2. Поместите две копии этого UserControl в контейнер (grid в примере ниже).

    а. Выровняйте первую верхнюю / верхнюю копию, чтобы она оставалась по умолчанию. Эта копия предназначена исключительно для целей измерения и должна иметь значение «Видимость» для «Скрыто».

    б. Поместите вторую копию в поле «Просмотр». Эта копия является той, которую пользователь действительно увидит.

  3. Используйте MultiBinding с MultiValueConverter, чтобы настроить ширину второго UserControl так, чтобы он имел правильное соотношение сторон, прежде чем он будет расширяться в Viewbox.

Вот разметка:

               

Вот MultiValueConverter

 public class WidthAdjuster : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { var rawHeight = (double)values[0]; var containerWidth = (double)values[1]; var containerHeight = (double)values[2]; var ratio = containerWidth / containerHeight; return rawHeight * ratio; } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } 

Результат для контейнера 525 x 350

alt text

У меня была почти такая же проблема. Моя панель должна была приспосабливать всех своих детей, помещая их в ряд и растягивая их, равномерно заполняя панель. Алгоритм выше использует преобразование рендеринга для элементов шкалы. Проблема заключается в том, что преобразование рендеринга растягивает самих детей, но игнорирует маржу. Если маржа высока, а масштабный коэффициент ниже 1, элементы выпадают из панели. Вы должны скорректировать масштаб для RenderTransform в соответствии с маржой на этой оси и использовать тот же масштабный коэффициент для организации. MeasureOverride, который я использовал, был

 protected override Size MeasureOverride(Size availableSize) { double width = 0; double maxHeight = 0; double mY=0; double mX=0; Size unlimitedSize = new Size(double.PositiveInfinity, double.PositiveInfinity); foreach (UIElement child in Children) { child.Measure(unlimitedSize); width += child.DesiredSize.Width; maxHeight = Math.Max(maxHeight, child.DesiredSize.Height); FrameworkElement cld = child as FrameworkElement; mY = cld.Margin.Top + cld.Margin.Bottom; mX = cld.Margin.Left + cld.Margin.Right; } double scaleX = availableSize.Width / width; double scaleY = availableSize.Height / maxHeight; //That is scale for arranging positionScaling = Math.Min(scaleX, scaleY); try { // Let FrameworkElement hight be Xn. mY = Element.Margin.Top + Element.Margin.bottom. // DesiredSize includes margin therefore: // (Yn + mY) * scaleY = availableSize.Height // But render transform doesn't scales margin. Actual render height with margin will be // Yn * RenderScaleY + mY = availableSize.Height; // We must find render transform scale coeff like this: double yn = availableSize.Height / scaleY - mY; scaleY = (availableSize.Height - mY) / yn; double xn = availableSize.Width / scaleX - mX; scaleX = (availableSize.Width - mX) / xn; scale = Math.Min(scaleX, scaleY); //scale to use in RenderTransform // In my project all children are similar in size and margin, algorithm BREAKS otherwise!!! } catch { scale = 1; } return availableSize; } 

Еще раз: в моем проекте все дети похожи по размеру и маржи, алгоритм BREAKS в противном случае.

  • Как вы выполняете эффекты перехода с помощью элемента управления Frame в WPF?
  • Загрузите ResourceDictionary из сборки
  • Где находится элемент управления UpDown WPF?
  • Как отключить цвет фона в TextBox в WPF
  • В чем разница между x: Reference и ElementName?
  • Как отключить Aero Snap в приложении?
  • WPF C #: переупорядочить элементы в списке с помощью перетаскивания
  • WPF: как программно удалить фокус из TextBox
  • Как загрузить изображение в WPF во время выполнения?
  • Анимация WPF: привязка к атрибуту «To» анимации раскадровки
  • Нет Main () в WPF?
  • Давайте будем гением компьютера.