WPF: как сделать (0,0) в центре внутри холста
У холста WPF есть система координат, начинающаяся с (0,0) в левом верхнем углу элемента управления.
Например, установка следующего параметра заставит мой элемент управления появиться в верхнем левом углу:
<Control Canvas.Left="0" Canvas.Top="0">
Как я могу изменить его на стандартные декартовы координаты?
В принципе:
Я заметил этот пост, но он не говорит о переводе системы координат. Я попытался добавить TranslateTransform, но я не могу заставить его работать.
Ответы
Ответ 1
Лучше всего написать пользовательский холст, в котором вы можете написать ArrangeOverride таким образом, чтобы в качестве центра он занимал 0,0.
Обновление: я дал еще один комментарий в следующем ответе (@decasteljau). Я не рекомендую выводить из Canvas. Вы можете получить из Panel и добавить два свойства Attached Dependancy Top и Left и поместить тот же код, который вы вставили выше. Также не нужен конструктор с LayoutTransform в нем, и не используйте какое-либо преобразование на код панели, используя надлежащую меру и организуйте на основе желаемого размера панели. Таким образом, вы также можете добиться хорошего поведения для изменения контента. Холст не динамически позиционирует элементы при изменении размера холста.
Ответ 2
Нет необходимости создавать настраиваемую панель. Canvas будет работать отлично. Просто оберните его внутри другого элемента управления (например, границы), центрируйте его, придайте ему нулевой размер и переверните его с помощью RenderTransform:
<Border>
<Canvas HorizontalAlignment="Center" VerticalAlignment="Center"
Width="0" Height="0"
RenderTransform="1 0 0 -1 0 0">
...
</Canvas>
</Border>
Вы можете сделать это, и все в холсте все равно появится, кроме (0,0) будет находиться в центре содержащего элемента управления (в этом случае центр границы) и + Y будут вместо вниз.
Опять же, не требуется для создания пользовательской панели для этого.
Ответ 3
Это было очень легко сделать. Я посмотрел оригинальный код Canvas с использованием .NET Reflector и заметил, что реализация на самом деле очень проста. Единственное, что нужно было, это переопределить функцию ArrangeOverride(...)
public class CartesianCanvas : Canvas
{
public CartesianCanvas()
{
LayoutTransform = new ScaleTransform() { ScaleX = 1, ScaleY = -1 };
}
protected override Size ArrangeOverride( Size arrangeSize )
{
Point middle = new Point( arrangeSize.Width / 2, arrangeSize.Height / 2 );
foreach( UIElement element in base.InternalChildren )
{
if( element == null )
{
continue;
}
double x = 0.0;
double y = 0.0;
double left = GetLeft( element );
if( !double.IsNaN( left ) )
{
x = left;
}
double top = GetTop( element );
if( !double.IsNaN( top ) )
{
y = top;
}
element.Arrange( new Rect( new Point( middle.X + x, middle.Y + y ), element.DesiredSize ) );
}
return arrangeSize;
}
}
Ответ 4
Вы можете просто изменить Origin с помощью RenderTransformOrigin
.
<Canvas Width="Auto" Height="Auto"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RenderTransformOrigin="0.5,0.5">
<Canvas.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleY="-1" ScaleX="1" />
</TransformGroup>
</Canvas.RenderTransform>
</Canvas>