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

  • Пользовательский курсор в WPF?
  • WPF C # Путь: как получить из строки с данными пути в геометрию в коде (не в XAML)
  • .NET Проблемы с памятью загружаются ~ 40 изображений, память не регенерирована, потенциально из-за fragmentации LOH
  • Использование правил проверки WPF и отключение кнопки «Сохранить»
  • Добавить информацию о форме в ListView, когда она создана
  • Как изменить источник изображения динамически из кода в WPF с изображением в свойствах. Ресурсы?
  • Можете ли вы определить несколько TargetTypes для одного стиля XAML?
  • Свяжите элемент с двумя источниками
  • Использование глобальной клавиатуры (WH_KEYBOARD_LL) в WPF / C #
  • Какая структура MVVM - лучшая структура для приложений WPF
  • Как я могу привязать данные строк к ListBox в WPF / WP7?
  • Interesting Posts

    Сравнение DES, Triple DES, AES, шифрование blowfish для данных

    Как оператор может быть перегружен для разных типов RHS и возвращаемых значений?

    Является ли размер std :: array определенным стандартом

    Оптимизация поиска MySQL с использованием «похожих» и подстановочных знаков

    Проложить маршруты с помощью API Карт Google v2

    Как удалить или отключить кнопку «Простота доступа» на экране входа в Windows 7

    Возвращать имена файлов в реестре в командной строке

    Отформатируйте текущую дату и время в VBScript

    Синглтоны: хороший дизайн или костыль?

    css: как рисовать круг с текстом в середине?

    Нельзя ли динамически использовать Generics?

    Драйвер дисплея перестает работать и был восстановлен.

    У Microsoft по-прежнему есть ссылка для загрузки IE10 для Windows 7?

    Является ли Intel i7 реальным улучшением по сравнению с предшественниками?

    Как ffmpeg определяет отдельные битрейты потока?

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