Создание треугольника с привязкой к данным?
У меня есть требование создать несколько фигур на основе предоставленного размера (все они имеют одинаковую высоту / ширину), и их размеры должны быть привязаны к данным этого предоставленного свойства в текстовом тексте данных.
Большинство форм просты: круг (эллипс с ограничением высоты / ширины), квадрат (прямоугольник с ограничением высоты / ширины), ромб (такой же, как квадрат, затем используйте RotateTransform), + (две строки), X (две строки),
Но я пытаюсь понять, как сделать это для треугольника, и я не могу понять это. Это должен быть заполненный объект, поэтому я не могу просто сделать это с тремя строками.
Но все способы, которые я видел, чтобы сделать это (с Path
или Polygon
в конечном итоге принимать Point
объекты (StartPoint
, EndPoint
, так далее). И вы не можете привязать к X
или же Y
значения Point
объект.
Я что-то пропустил? Или мне нужно написать свою собственную форму или что-то в этом роде?
Изменить: Чтобы добавить немного ясности... тип треугольника, который я создаю, на самом деле не имеет значения. Это может быть равносторонний или равнобедренный. Я нацелился на равнобедренный, чтобы у него была база с шириной границы данных, а верхний "кончик" треугольника будет в средней точке ширины границы данных и при Y=0. Это была просто оптимизация ради простоты
2 ответа
Класс поведения:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Shapes;
using System.Windows.Media;
namespace WpfApplication1
{
public enum ShapeType
{
Rectangle,
Isosceles,
Ellipse,
Dice,
Hexagon
}
public class PathControl
{
public static readonly DependencyProperty ShapeTypeProperty =
DependencyProperty.RegisterAttached("ShapeType",
typeof(ShapeType?),
typeof(DependencyObject),
new PropertyMetadata(null,
new PropertyChangedCallback((sender, args) =>
{
Path path = sender as Path;
ShapeType? shapeType = (ShapeType?)args.NewValue;
//todo: use a WeakEvent
path.SizeChanged +=
(pathSender, pathArgs) =>
{
PathControl.InvalidatePath((Path)sender, shapeType);
};
})));
private static void InvalidatePath(Path path, ShapeType? shapeType)
{
if (path != null
&& shapeType.HasValue)
{
string source = null;
double netWidth = path.Width - 2 * path.StrokeThickness,
netHeight = path.Height - 2 * path.StrokeThickness;
if (shapeType == ShapeType.Rectangle)
{
source = string.Format("M0,0 h{0} v{1} h-{0} z",
new object[2]
{
netWidth,
netHeight
});
}
else if (shapeType == ShapeType.Isosceles)
{
source = string.Format("M0,{1} l{0},-{1} {0},{1} z",
new object[2]
{
netWidth / 2,
netHeight
});
}
else
{
throw new NotImplementedException(shapeType.ToString());
}
path.Data = Geometry.Parse(source);
}
}
public static void SetShapeType(DependencyObject o, ShapeType e)
{
o.SetValue(PathControl.ShapeTypeProperty, e);
}
public static ShapeType? GetShapeType(DependencyObject o)
{
return (ShapeType)o.GetValue(PathControl.ShapeTypeProperty);
}
}
}
XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:local="clr-namespace:WpfApplication1">
<Grid>
<Path Width="100" Height="100" Stroke="Green" StrokeThickness="2" Fill="Yellow"
local:PathControl.ShapeType="Isosceles">
<Path.RenderTransform>
<RotateTransform Angle="90"></RotateTransform>
</Path.RenderTransform>
</Path>
</Grid>
</Window>
Привязка к точкам является лучшим / единственным способом. X и X свойства Point не могут быть связаны, потому что они не вызывают событие PropertyChanged. Точка - это структура, и структуры должны быть доступны только для чтения.
Класс PointCollection вызывает правильные события, чтобы вы могли связываться с ним. Это позволяет вам манипулировать треугольниками, изменяя набор точек путем замены точек. Не меняйте точку, а заменяйте их, чтобы были подняты правильные события.