Создание шкалы 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 в противном случае.

  • Как сортировать элементы TreeView с помощью SortDescriptions в Xaml?
  • Поместите элемент управления WPF в форму Windows Forms
  • Загрузите ResourceDictionary из сборки
  • WPF: кнопка с одним щелчком мыши + двойной щелчок
  • Можно ли связать свойство Canvas's Children в XAML?
  • Режим рендеринга программ - WPF
  • Как отформатировать TimeSpan в XAML
  • Взаимоисключающие элементы меню?
  • Обработка события закрытия windows с помощью WPF / MVVM Light Toolkit
  • Какая структура MVVM - лучшая структура для приложений WPF
  • Доступ к родительскому DataContext из DataTemplate
  • Interesting Posts

    xpath: найти узел, атрибут classа которого соответствует значению и текст которого содержит определенную строку

    Какой код установки должен идти в Form Constructors по сравнению с событием Form Load?

    Лучший способ включить Volley (или другую библиотеку) в проект Android Studio

    Как использовать поддержку FileProvider для обмена контентом с другими приложениями?

    Как предотвратить захват / захват нажатия клавиш веб-сайтами в Firefox?

    Маршрутизация трафика IPv6 через pptpd Debian в туннель IPv6 Hurricane Electric

    Unity EventManager с делегатом вместо UnityEvent

    Строка Parse Json в C #

    Ссылка на Schema.org JSON-LD

    Форсировать текст / цвет фона в раскрывающемся меню в Firefox.

    Как установитьContentView в fragmentе?

    В C # Winforms есть способ поместить пунктирную границу вокруг всех элементов управления и показать точки захвата при выборе определенных элементов управления во время выполнения?

    Чрезвычайно высокая активность на диске без реального использования

    Не удалось удалить flash9.ocx

    Как работает удаленная программа, например Team Viewer?

    Давайте будем гением компьютера.