2012-03-12 4 views
4

Проще говоря, я хочу создать некоторые атрибуты resize/rescale для прикрепления к FrameworkElement, которые позволят пользователю изменять размер элемента, если они обычно используют обложки, и позволят им перемасштабировать элемент (необязательно равномерно), если они используют нижний правый adorner и удерживайте кнопку SHIFT во время этого.Как создать украшения, которые не масштабируются с помощью AdornedElement?

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

Во-первых, , когда я масштабирую элемент более чем (примерно) на 2x, поведение масштабирования ломается и начинает прыгать повсюду.

Очевидно, что это поведение легче увидеть, чем описать, поэтому я приложил образец решения (VS 2010), демонстрирующий проблему и код, который ее вызывает.

Example VS 2010 solution

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

Кроме того, чтобы иметь в виду, что этот adorner также должен будет отображаться правильно, если базовый украшенный элемент повернут, что в настоящее время он не будет.

Обновление: Просто держать NVM счастливой, вот решение делает это его путь: NVM's way

ответ

6

Если у вас есть большие пальцы внутри Adorner для перетаскивания/вращающихся и т.д., вы будете первым хотите, чтобы остановить их масштабирование, так что вы делаете это в переопределении GetDesiredTransform. Примените обратную шкалу, которую вы применили к элементу framework. Это делает ваши большие пальцы не масштабируемыми при изменении размера.

public override GeneralTransform GetDesiredTransform(GeneralTransform transform) 
{ 
    double scaleFactor = GetCurrentScaleFactor(this._parent); 

    if (this._visualChildren != null) 
    { 
     foreach (var thumb in this._visualChildren.OfType<Thumb>()) 
     { 
      thumb.RenderTransform 
       = new ScaleTransform(1/scaleFactor , 1/scaleFactor); 
      thumb.RenderTransformOrigin = new Point(0.5, 0.5); 
     } 
    } 

    return base.GetDesiredTransform(transform); 
} 

Следующая проблема будет аранжировать пальцы так, что они в конечном итоге в правильных местах после масштабирования/вращающаяся и т.д. Так как вы изменили Рендер преобразования для большого пальца вы должны теперь вручную организовать его с помощью ArrangeOverride ,

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

protected override Size ArrangeOverride(Size finalSize) 
{ 
    var adornedElement = this.AdornedElement as FrameworkElement; 

    // Use the width/height etc of adorned element to arrange the thumbs here 
    // Its been a long time so either its width/height or actualwidth/actualheight 
    // you will need to use. 
    this._leftTopThumb.Arrange(Get the Rect To arrange here); 
    this._rightTopThumb.Arrange(Get the Rect To arrange here); 
    // etc 

    return finalSize; 
} 

Если вы не знаете, как сделать код проекта статьи организовать материал See This.

Если вы все еще не можете заставить его работать, покажите нам соответствующий код (а не визуальное студийное решение), что, вероятно, вызовет проблемы, и кто-то поможет вам, я уверен.

EDIT

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

  1. Удалите все превьюмеры и обработчики событий, за исключением большого пальца btmRight.
  2. Добавить событие DragCompleted в btmRight Thumb.(Удалить сопротивление дельты)

По существу суть коды задачи сводится к комментировали линию:

void _btmRight_DragCompleted(object sender, DragCompletedEventArgs e) 
{ 
    var adornedElement = AdornedElement as FrameworkElement; 
    var hitThumb = sender as Thumb; 
    if (adornedElement == null || hitThumb == null) return; 

    var transformGroup = new TransformGroup(); 
    transformGroup.Children.Add(adornedElement.RenderTransform); 

    //---- This is the problem line 
    transformGroup.Children.Add(new ScaleTransform(1 + e.HorizontalChange/adornedElement.Width, 1 + e.VerticalChange/adornedElement.Height)); 
    //------------------------------- 

    adornedElement.RenderTransform = new MatrixTransform(transformGroup.Value); 
    } 

Теперь его легко выяснить проблему. Этот фрагмент кода отлично работает при первом перетаскивании и изменении размера. Это потому, что adornedElement.Width и adornedElement.Height верны, когда вы перетаскиваете его в первый раз, пока не применяются масштабные преобразования. Как только ваше перетаскивание завершено, вы предполагаете, что теперь ширина и высота будут новой шириной и высотой. Их нет! Вы видите, что это просто преобразование рендера, оно не меняет ширину или высоту элемента. Это просто делает его больше.

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

У вас наверняка возникнут другие проблемы при выполнении этого в DragDelta. Но в этом случае вы должны задать более конкретный вопрос только с небольшим количеством соответствующего кода, и вы получите ответ от кого-то через несколько минут, я уверен.

+0

Полезно, однако оно почти идентично тому, что я уже сделал И страдает от той же проблемы, что и моя. Он * все еще работает отлично до 2x, затем идет умственно. – Siyfion

+0

Мое предложение исходит из кода в реальном времени, работающего на машинах более 200 тыс., И позволяет изменять размер/вращение/перемещение/обрезку и множество других вещей. Если вы не можете заставить его работать, вы делаете что-то неправильно. Выделять свой вопрос смело не улучшает его. Показывать свой код с тем, что вы сделали. Просто догадываетесь: какие большие пальцы вы используете (это очень большое следствие), они шаблоны отличаются от стандартных? – NVM

+0

Я не говорю, что это ваш код, который вызывает проблему, я говорю, что проблема, с которой я изначально сталкивалась, по-прежнему существует в вашем способе делать что-то. Что касается примера кода, извините, но нет, я не буду публиковать все 2 * .xaml и 2 * .cs файлы, когда будет достаточно простой ссылки. Сделать это смелым было так, чтобы кто-либо другой понял, что мой «основной» вопрос был, это было не для вас. И никакие мои большие пальцы в настоящее время не замаскированы шаблонами, хотя они будут в будущем. – Siyfion

1

Siyfion, явление, которое вы видите, является реальным. Причина в том, что вы не компенсируете тем же масштабированием при обработке перетаскивания Adorner. В дополнении к ответу NVM, убедитесь, что у вас также есть это:

double deltaX = args.HorizontalChange/CurrentDisplayScaleX; 
double deltaY = args.VerticalChange/CurrentDisplayScaleX; 

, где Вы получаете текущий масштаб отображения таким же образом. С этими исправленными значениями прыжки вокруг прекратятся. Спрыгивание - это фактически двойной рисунок, сначала система автоматически, используя неправильное масштабирование, во-вторых, используя измененные, правильные размеры, предоставленные вами. Он появляется на всех уровнях шкалы, только если он становится действительно очевидным, как только масштабирование начинает увеличиваться.