需求 具体描述 (待)实现方式(/ 思路)
图表添加指示线条 添加竖向可移动的线条来指出瑕疵落点位置 使用对应的控件方法处理

实现方案:

(插件实现)对图表控件添加事件控制逻辑

使用如下变量来存储状态信息和选中的线条对象

1
2
3
4
5
6
7
8
9
//鼠标状态
bool MouseDown = false;
//命中状态
bool StripSelected = false;
bool AxisXSelected = false;
bool AxisYSelected = false;

//当前被选中的线条
StripLine SelectedLine;

在 MouseMove 事件中的逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
MainWnd.ActiveControl = chart;
HitTestResult hit = chart.HitTest(Args.X, Args.Y);
//首先判断是否在图表范围内,然后判断当前是否有鼠标按键按下。

//只在范围内触发事件
if (hit.ChartElementType == ChartElementType.Nothing)
{
SelectedLine = null;
StripSelected = false;
MouseDown = false;
return;
}

if (MouseDown)
{
//有鼠标按下时
//移动元素
//chart.ChartAreas[0].AxisX.MajorGrid.LineWidth = 1;

//判断当前指针命中的元素

//判断是否选中轴线
if (AxisXSelected) { }

if (AxisYSelected)
{
//创建线条
var area = chart.ChartAreas[0];
var vx = area.AxisX.PixelPositionToValue(Args.X);

//切换到选中StripLine的状态
StripSelected = true;
SelectedLine = AddLineV(vx);
AxisYSelected = false;
}

//判断是否选中Stripline
if (StripSelected)
{
//如果存在线条被选中:移动线条
if (SelectedLine != null)
{
var x = chart.ChartAreas[0].AxisX.PixelPositionToValue(Args.X);
var max = chart.ChartAreas[0].AxisX.Maximum;
if (x > 0 && x < max)
SelectedLine.IntervalOffset = x;
Console.WriteLine(x);
}

}
else
chart.Cursor = Cursors.Default;
}
else
{
//指针命中元素
//根据命中位置修改指针状态

//判断是否命中轴线
if (hit.ChartElementType == ChartElementType.Axis)
{
Axis axis = (Axis)hit.Axis;
if (axis.Name == "Y (Value) axis")
{
//Y轴
chart.Cursor = Cursors.SizeWE;
}
else if (axis.Name == "X axis")
{
//X轴
//chart.Cursor = Cursors.SizeNS;
}

}

//判断是否命中StripLine
else if (hit.ChartElementType == ChartElementType.StripLines)
{
chart.Cursor = Cursors.SizeWE;

}
else
chart.Cursor = Cursors.Default;

}

MouseDown 事件中的逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
MouseDown = true;
HitTestResult hit = chart.HitTest(Args.X, Args.Y);

//判断是否命中轴线
if (hit.ChartElementType == ChartElementType.Axis)
{
//根据命中位置修改轴线选择状态
Axis axis = (Axis)hit.Axis;
if (axis.Name == "Y (Value) axis")
{
//Y轴
AxisYSelected = true;
}
else if (axis.Name == "X axis")
{
//X轴

}
else
{
AxisXSelected = false;
AxisYSelected = false;
}

}

//根据命中位置修改当前选中的线条
if (!StripSelected)
{

if (hit.ChartElementType == ChartElementType.StripLines)
{
SelectedLine = (StripLine)hit.Object;
StripSelected = true;
Console.WriteLine(SelectedLine);
}
}

在 MouseUp 事件中清除选中状态

1
2
3
4
5
MouseDown = false;
SelectedLine = null;
StripSelected = false;
AxisYSelected = false;
AxisXSelected = false;

在 KeyDown 事件中添加删除线条的功能,具体代码不再赘述。

最终效果:

添加线条(操作方式为指针放置到 Y 轴然后向右拖动)

image-20221017183718325

移动线条(操作方式为鼠标选中对应线条后拖动)

image-20221017183752937

删除线条(操作方式为鼠标选中对应线条之后按 Delete 键)

image-20221017183819482

目前存在的问题:选中元素使用了 Hit 对象,网格线的 hit 优先级比创建的 Strip Line 线条更高,因此当指针移动到靠近网格线时会出现无法选中 Strip Line 的情况;

对应的解决方案:添加显示 / 隐藏网格线的快捷键 Ctrl 键,当隐藏网格线时可以正确的命中对应的线条,当需要显示网格线时,再使用相应快捷键显示网格线。

效果图:

image-20221017184402268