`System.Windows.Point`用类替换结构

本文关键字:替换 结构 Point System Windows | 更新日期: 2023-09-27 18:23:36

我需要类似于System.Windows.Point的类型,但我需要类,而不是结构。

背景

我试着创建一些点,并将它们放在列表中,然后更改它们的坐标。

我的代码相当于:

List<Point> listofpoints = new List<Point>();
listofpoints.Add(new Point(1, 1));
listofpoints.Add(new Point(5, 5));
Line line = new Line();
line.Brush = new SolidColorBrush(Colors.Black);
line.X1 = listofpoints[0].X;
line.Y1 = listofpoints[0].X;
line.X2 = listofpoints[1].X;
line.Y2 = listofpoints[1].X;
canvas1.Children.Add(line);

// later I had to change these points coordinates
// I tried to move shapes with these points by changing only these point properties
listofpoints[0].X = 50;
listofpoints[0].Y = 50;
// but i cant, (probably) because struct is not reference type

我有什么

我写了一个简单的类,让我能够改变列表中的点,而不需要用新的点来替换它们。

public class CPoint
{ 
    public double X;
    public double Y;
}

我想要什么

我希望这个类的行为像System.Windows.Point结构。我的意思是,我希望能够用CPoint创建矩形,如下所示:

CPoint cp1 = new CPoint();
cp1.X = 0;
cp1.Y = 0;
CPoint cp2 = new CPoint();
cp2.X = 10;
cp2.Y = 20;
Rect r = new Rect(cp1, cp2); // this is just example, in fact - I use other shapes
// i want to be able to move that rectangle by only changing cp1 and cp2 properties.

这可能吗

我需要一些访问者吗?我知道如何生成返回某些属性的访问器,但不知道如何编写返回整个类的访问器。

`System.Windows.Point`用类替换结构

实现隐式转换运算符:

public class CPoint
{ 
    public double X;
    public double Y;
    public static implicit operator Point(CPoint cpoint)
    {
        return new Point(cpoint.X, cpoint.Y);
    }
    public static implicit operator CPoint(Point point)
    {
        return new CPoint(point.X, point.Y);
    }
}

这意味着,无论您在哪里尝试使用需要PointCPoint(反之亦然),编译器都会插入对这些转换运算符的调用。因此,您的使用将完全符合您的要求:

Rect r = new Rect(cp1, cp2);

然而,根据您的代码注释AFAIK,一旦您创建了Rect,如果您随后更改cp1.X = 9000以使其自动传播到该Rect,那么就不可能这样做,尤其是因为Rect本身是一个结构。我认为,如果这是你想要实现的,你必须考虑完全不同的设计/用途。

编辑:根据您的需求,可能需要考虑的设计如下。首先,定义您的CPoint以在其属性更改时发出通知:

public class CPoint
{ 
    public event Action<CPoint, double> XChanged;
    public event Action<CPoint, double> YChanged;
    private double _X;
    public double X
    {
        get { return _X; }
        set
        {
            _X = value;
            var xchanged = XChanged;
            if (xchanged != null)
                xchanged(this, value);
        }
    }
    private double _Y;
    public double Y
    {
        get { return _Y; }
        set
        {
            _Y = value;
            var ychanged = YChanged;
            if (ychanged != null)
                ychanged(this, value);
        }
    }
    public CPoint()
    {
    }
    public CPoint(double x, double y)
    {
        this._X = x;
        this._Y = y;
    }
}

然后,因为我认为,你的意图是用多条线共享同一点(例如绘制N边多边形),将线与点连接起来:

List<CPoint> listofpoints = new List<CPoint>();
listofpoints.Add(new CPoint(1, 1));
listofpoints.Add(new CPoint(5, 5));
Line line = new Line();
line.Brush = new SolidColorBrush(Colors.Black);
listofpoints[0].XChanged += (p, x) => line.X1 = x;
listofpoints[0].YChanged += (p, y) => line.Y1 = y;
listofpoints[1].XChanged += (p, x) => line.X2 = x;
listofpoints[1].YChanged += (p, y) => line.Y2 = y;
line.X1 = listofpoints[0].X;
line.Y1 = listofpoints[0].X;
line.X2 = listofpoints[1].X;
line.Y2 = listofpoints[1].X;
canvas1.Children.Add(line);

请注意XChangedYChanged事件的侦听器,以及它们如何与Line的X1、X2 , Y1 , Y2`属性相关联。

假设你也会将这些点用于其他形状,这样它们就不会与任何一种形状类型绑定。

listofpoints[0].X = 50; //propagates to line.X1 via the event
listofpoints[0].Y = 50; //propagates to line.Y1 via the event

分配事件将初始值分配给行有点重复,但我相信如果必要的话,进行一些调整会消除这种情况。

否,不能通过改变矩形的组成点来移动矩形。这是故意的。WPF确实允许您通过数据绑定和依赖属性来做您想做的事情。

特别是对于矩形,您希望绑定到RadiusX和RadiusY属性,因为它们是矩形提供的可绑定依赖属性。

将Rectangle绑定到模型对象时,请确保模型对象实现INotifyPropertyChanged或提供自己的依赖属性。

有关WPF数据绑定的更多信息,请查看此处。