Создание треугольника с привязкой к данным?

У меня есть требование создать несколько фигур на основе предоставленного размера (все они имеют одинаковую высоту / ширину), и их размеры должны быть привязаны к данным этого предоставленного свойства в текстовом тексте данных.

Большинство форм просты: круг (эллипс с ограничением высоты / ширины), квадрат (прямоугольник с ограничением высоты / ширины), ромб (такой же, как квадрат, затем используйте 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 вызывает правильные события, чтобы вы могли связываться с ним. Это позволяет вам манипулировать треугольниками, изменяя набор точек путем замены точек. Не меняйте точку, а заменяйте их, чтобы были подняты правильные события.

Другие вопросы по тегам