博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[WPF] [AMindMap] 开发手记-4 (UI ANode的在代码中触发动画)
阅读量:6871 次
发布时间:2019-06-26

本文共 15404 字,大约阅读时间需要 51 分钟。

一路下来,ANode的大体结构基本要完工了,我之所以说这是个结构,因为,这是一次

渐进式开发,各个部分的处理方式,大体上已经确定下来了,如有后续内容,将依照现在

的模式去做。

关于 动画 的 触发

今天说一下代码中触发动画,这个话题其实很短,那就加上,ANode的一个简单测试环境

其实也是,后面我们UI主窗口的一个基本结构。

 

从代码中触发动画其实只有一句话,简单到不行。

BeginStoryboard(Me.Resources.Item("SelectedStatus"))

SelectedStatus就是我们当初在Xaml中定义的画板,用BeginStoryboard执行一下,就

Ok。

 

ANode的事件触发,目前的几种状态触发,我都是通过代码实现的,因为,在触发的同时

要抛出事件,还有设置状态标识,为了统一起见,我都放在代码中实现了。

还是列表的形式来说明各个状态是在什么情况下出现的吧

ANode的状态触发条件      
状态 触发条件 附加条件 响应
选中状态 鼠标进入ANode 非编辑状态 1.触发动画
2.设置当前ANode为活动
(关系到失去焦点的ANode,恢复正常状态)
3.抛出OnSelected事件
  鼠标在NodeGrid上抬起 1.触发动画
2.抛出DragEnd事件
拖放状态 鼠标在NodeGrid上按下 1.触发动画
2.抛出DragStart事件
编辑状态 鼠标在NodeTextInput上抬起 1.触发动画
2.设置IsEdit标志位
正常状态 自定义方法SetNormal 1.触发动画
2.设置IsEdit=False

 

在这里要先说明一下,ANode在主界面上,会有很多很多,但是,每次选中的只有一个,

不会存在多选的形式(至少目前,我所预期的方式不会),那么当ANode被选中时,将取消

上一个被选中的ANode,在这里我用了一个Shared方法,来实现同一的管理。

 
1
Private
Shared
ActiveNode
As
ANode
2
3
Private
Shared
Sub
SetActiveNode(
ByVal
n
As
ANode)
4
If
Not
ActiveNode
Is
Nothing
Then
5
If
Not
ActiveNode.Equals(n)
Then
6
ActiveNode.ZIndex
=
0
7
ActiveNode.SetNormal()
8
End
If
9
End
If
10
ActiveNode
=
n
11
If
Not
n
Is
Nothing
Then
12
n.ZIndex
=
1
13
End
If
14
End Sub
15
16
Public
Shared
Sub
SetAllNormal()
17
SetActiveNode(
Nothing
)
18
End Sub

一个静态的变量标识这整个ANode群的活动单元,一个私有的SetActiveNode,

用来当当前单元被选中时将自己设置为活动单元,并取消前一个单元的活动状态。

并且,加了一个SetAllNormal方法,给外部提供的全部取消活动的法。

 

以下是各个状态相关的方法和变量的代码

 

 
1
2
#Region
" 选择状态 "
3
Public
Event
OnSelected(
ByVal
sender
As
ANode)
4
5
Private
Sub
NodeGrid_MouseEnter(
ByVal
sender
As
Object
,
ByVal
e
As
System.Windows.Input.MouseEventArgs)
Handles
NodeGrid.MouseEnter
6
If
IsEdit
Then
Exit Sub
7
SetActiveNode(
Me
)
8
BeginStoryboard(
Me
.Resources.Item(
"
SelectedStatus
"
))
9
RaiseEvent
OnSelected(
Me
)
10
End Sub
11
#End Region
12
13
#Region
" 拖放状态 "
14
Public
Event
OnDragStart(
ByVal
sender
As
ANode,
ByVal
DragPoint
As
Point)
15
Public
Event
OnDragEnd(
ByVal
sender
As
ANode)
16
17
Private
Sub
NodeGrid_MouseDown(
ByVal
sender
As
Object
,
ByVal
e
As
System.Windows.Input.MouseButtonEventArgs)
Handles
NodeGrid.MouseDown
18
BeginStoryboard(
Me
.Resources.Item(
"
DragStatus
"
))
19
RaiseEvent
OnDragStart(
Me
, e.GetPosition(sender))
20
e.Handled
=
True
21
End Sub
22
23
Private
Sub
NodeGrid_MouseUp(
ByVal
sender
As
Object
,
ByVal
e
As
System.Windows.Input.MouseButtonEventArgs)
Handles
NodeGrid.MouseUp
24
BeginStoryboard(
Me
.Resources.Item(
"
SelectedStatus
"
))
25
RaiseEvent
OnDragEnd(
Me
)
26
End Sub
27
#End Region
28
29
#Region
" 编辑状态 "
30
Private
IsEdit
As
Boolean
=
False
31
Private
Sub
NodeTextInput_PreviewMouseDown(
ByVal
sender
As
Object
,
ByVal
e
As
System.Windows.Input.MouseButtonEventArgs)
Handles
NodeTextInput.PreviewMouseDown
32
BeginStoryboard(
Me
.Resources.Item(
"
EditStatus
"
))
33
IsEdit
=
True
34
End Sub
35
#End Region
36
37
#Region
" 普通状态 "
38
Public
Sub
SetNormal()
39
BeginStoryboard(
Me
.Resources.Item(
"
NormalStatus
"
))
40
IsEdit
=
False
41
End Sub
42
#End Region
43
44
#Region
" ActiveNode "
45
Private
Shared
ActiveNode
As
ANode
46
47
Private
Shared
Sub
SetActiveNode(
ByVal
n
As
ANode)
48
If
Not
ActiveNode
Is
Nothing
Then
49
If
Not
ActiveNode.Equals(n)
Then
50
ActiveNode.ZIndex
=
0
51
ActiveNode.SetNormal()
52
End
If
53
End
If
54
ActiveNode
=
n
55
If
Not
n
Is
Nothing
Then
56
n.ZIndex
=
1
57
End
If
58
End Sub
59
60
Public
Shared
Sub
SetAllNormal()
61
SetActiveNode(
Nothing
)
62
End Sub
63
#End Region

至此,ANode貌似就差不多介绍完了

哦,还有几个属性,Text,Background,Foreground,ZIndex

为了可以支持绑定,这些属性都是DependencyProperty。

代码也贴一下。

 
1
2
#Region
" Text DependencyProperty "
3
'''
<summary>
4
'''
PropertyComment
5
'''
</summary>
6
'''
<remarks></remarks>
7
Public
Shared
ReadOnly
TextProperty
As
DependencyProperty
=
_
8
DependencyProperty.Register(
9
"
Text
"
,
GetType
(
String
),
GetType
(ANode),
New
PropertyMetadata( _
10
""
,
New
PropertyChangedCallback(
AddressOf
TextPropertyChanged_CallBack)))
11
12
Public
Property
Text()
As
String
13
Get
14
Return
GetValue(TextProperty)
15
End
Get
16
Set
(
ByVal
Value
As
String
)
17
SetValue(TextProperty, Value)
18
End
Set
19
End Property
20
21
Public
Shared
Sub
TextPropertyChanged_CallBack(
ByVal
dp
As
DependencyObject,
ByVal
e
As
DependencyPropertyChangedEventArgs)
22
23
End Sub
24
#End Region
25
26
#Region
" BackgroundColor DependencyProperty "
27
'''
<summary>
28
'''
PropertyComment
29
'''
</summary>
30
'''
<remarks></remarks>
31
Public
Shared
ReadOnly
BackgroundColorProperty
As
DependencyProperty
=
_
32
DependencyProperty.Register(
33
"
BackgroundColor
"
,
GetType
(Brush),
GetType
(ANode),
New
PropertyMetadata( _
34
Brushes.LightBlue,
New
PropertyChangedCallback(
AddressOf
BackgroundColorPropertyChanged_CallBack)))
35
36
Public
Property
BackgroundColor()
As
Brush
37
Get
38
Return
GetValue(BackgroundColorProperty)
39
End
Get
40
Set
(
ByVal
Value
As
Brush)
41
SetValue(BackgroundColorProperty, Value)
42
End
Set
43
End Property
44
45
Public
Shared
Sub
BackgroundColorPropertyChanged_CallBack(
ByVal
dp
As
DependencyObject,
ByVal
e
As
DependencyPropertyChangedEventArgs)
46
Dim
an
As
ANode
=
CType
(dp, ANode)
47
an.NodeBackground.Background
=
e.NewValue
48
an.NodeBackground.BorderBrush
=
e.NewValue
49
With
CType
(e.NewValue, SolidColorBrush).Color
50
Dim
brightness
As
Integer
=
Math.Max(.R, Math.Max(.G, .B))
51
If
brightness
<
127
Then
52
an.ForegroundColor
=
Brushes.White
53
Else
54
an.ForegroundColor
=
Brushes.Black
55
End
If
56
End
With
57
End Sub
58
#End Region
59
60
#Region
" ForegroundColor DependencyProperty "
61
'''
<summary>
62
'''
PropertyComment
63
'''
</summary>
64
'''
<remarks></remarks>
65
Public
Shared
ReadOnly
ForegroundColorProperty
As
DependencyProperty
=
_
66
DependencyProperty.Register(
67
"
ForegroundColor
"
,
GetType
(Brush),
GetType
(ANode),
New
PropertyMetadata( _
68
Brushes.Black,
New
PropertyChangedCallback(
AddressOf
ForegroundColorPropertyChanged_CallBack)))
69
70
Public
Property
ForegroundColor()
As
Brush
71
Get
72
Return
GetValue(ForegroundColorProperty)
73
End
Get
74
Set
(
ByVal
Value
As
Brush)
75
SetValue(ForegroundColorProperty, Value)
76
End
Set
77
End Property
78
79
Public
Shared
Sub
ForegroundColorPropertyChanged_CallBack(
ByVal
dp
As
DependencyObject,
ByVal
e
As
DependencyPropertyChangedEventArgs)
80
Dim
an
As
ANode
=
CType
(dp, ANode)
81
an.NodeText.Foreground
=
e.NewValue
82
End Sub
83
#End Region
84
85
#Region
" ZIndex DependencyProperty "
86
'''
<summary>
87
'''
PropertyComment
88
'''
</summary>
89
'''
<remarks></remarks>
90
Public
Shared
ReadOnly
ZIndexProperty
As
DependencyProperty
=
_
91
DependencyProperty.Register(
92
"
ZIndex
"
,
GetType
(
Double
),
GetType
(ANode),
New
PropertyMetadata( _
93
0.0
,
New
PropertyChangedCallback(
AddressOf
ZIndexPropertyChanged_CallBack)))
94
95
Public
Property
ZIndex()
As
Double
96
Get
97
Return
GetValue(ZIndexProperty)
98
End
Get
99
Set
(
ByVal
Value
As
Double
)
100
SetValue(ZIndexProperty, Value)
101
End
Set
102
End Property
103
104
Public
Shared
Sub
ZIndexPropertyChanged_CallBack(
ByVal
dp
As
DependencyObject,
ByVal
e
As
DependencyPropertyChangedEventArgs)
105
106
End Sub
107
#End Region

Ok,ANode就完事儿了。

那么就搞一个对ANode的测试页面吧。

测试页 的 构建

建立一个Wpf应用程序工程

MainWindowViewModel

 
1
Imports
System.Collections.ObjectModel
2
3
Public
Class
MainWindowViewModel
4
Inherits
NotificationObject
5
'
6
'
NodeList As ObservableCollection(Of Node)
7
'
8
Private
mNodeList
As
ObservableCollection(
Of
Node)
9
Public
Property
NodeList()
As
ObservableCollection(
Of
Node)
10
Get
11
If
mNodeList
Is
Nothing
Then
12
mNodeList
=
New
ObservableCollection(
Of
Node)
13
End
If
14
Return
mNodeList
15
End
Get
16
Set
(
ByVal
Value
As
ObservableCollection(
Of
Node))
17
mNodeList
=
Value
18
RaisePropertyChanged(
"
NodeList
"
)
19
End
Set
20
End Property
21
22
Public
Sub
New
()
23
Dim
newNode
As
New
Node
24
newNode.Text
=
"
新主题
"
25
newNode.Top
=
100
26
newNode.Left
=
50
27
newNode.ZIndex
=
0
28
newNode.Background
=
Brushes.LightCoral
29
NodeList.Add(newNode)
30
Dim
node2
As
New
Node
31
node2.Text
=
"
副本
"
32
node2.Left
=
200
33
node2.Top
=
100
34
node2.ZIndex
=
0
35
node2.Background
=
Brushes.Black
36
NodeList.Add(node2)
37
Dim
node3
As
New
Node
38
With
node3
39
.Text
=
"
副本
"
40
.Left
=
300
41
.Top
=
100
42
.ZIndex
=
0
43
.Background
=
Brushes.Black
44
End
With
45
46
NodeList.Add(node3)
47
End Sub
48
49
End Class
50

有一个用于绑定的NodeList属性。

 

为了简便起见,我自定义了NotificationObject类,而并没有引入Prism工具,

在ViewModel文件夹中,以后还是再建一个文件夹存放吧,现在稍显凌乱,也无伤大雅

关于NotificationObject,给不了解的同学补充一点东西吧,看代码。

 
1
Public
Class
NotificationObject
2
Implements
ComponentModel.INotifyPropertyChanged
3
4
Public
Event
PropertyChanged(
ByVal
sender
As
Object
,
ByVal
e
As
System.ComponentModel.PropertyChangedEventArgs)
Implements
System.ComponentModel.INotifyPropertyChanged.PropertyChanged
5
6
Public
Sub
RaisePropertyChanged(
ByVal
propertyName
As
String
)
7
RaiseEvent
PropertyChanged(
Me
,
New
System.ComponentModel.PropertyChangedEventArgs(propertyName))
8
End Sub
9
End Class
10

MVVM中,为了让绑定的属性跟控件属性建立真正的联系也就是说,当被绑定属性(ViewModel

或Model中的属性)变化时,在控件上有所体现,Model或ViewModel必须实现

INotifyPropertyChanged接口,以便于通知控件属性变化,在ViewModel或Model中的属性

要这样写

 
1
2
Private
mText
As
String
3
Public
Property
Text()
As
String
4
Get
5
Return
mText
6
End
Get
7
Set
(
ByVal
Value
As
String
)
8
mText
=
Value
9
RaisePropertyChanged(
"
Text
"
)
10
End
Set
11
End Property
12

第9行,就是用来通知控件的。当然这里也要强调,控件属性必须是DependencyProperty才

能够被绑定。

Node类 对应与ANode,实现了几个需要被存储,和用于操作ANode在界面上的效果的几个属性。

这里,还有待于探讨,因为为了简便实现,Node参与了UI层的东西,而配合操作ANodeUI元素的

东西应该出现在ViewModel层。

 

 
1
2
Public
Class
Node
3
Inherits
NotificationObject
4
5
'
6
'
Text As String
7
'
8
Private
mText
As
String
9
Public
Property
Text()
As
String
10
Get
11
Return
mText
12
End
Get
13
Set
(
ByVal
Value
As
String
)
14
mText
=
Value
15
RaisePropertyChanged(
"
Text
"
)
16
End
Set
17
End Property
18
19
'
20
'
Left As Double
21
'
22
Private
mLeft
As
Double
23
Public
Property
Left
()
As
Double
24
Get
25
Return
mLeft
26
End
Get
27
Set
(
ByVal
Value
As
Double
)
28
mLeft
=
Value
29
RaisePropertyChanged(
"
Left
"
)
30
End
Set
31
End Property
32
33
'
34
'
Top As Double
35
'
36
Private
mTop
As
Double
37
Public
Property
Top()
As
Double
38
Get
39
Return
mTop
40
End
Get
41
Set
(
ByVal
Value
As
Double
)
42
mTop
=
Value
43
RaisePropertyChanged(
"
Top
"
)
44
End
Set
45
End Property
46
47
'
48
'
ZIndex As integer
49
'
50
Private
mZIndex
As
Integer
=
0
51
Public
Property
ZIndex()
As
Integer
52
Get
53
Return
mZIndex
54
End
Get
55
Set
(
ByVal
Value
As
Integer
)
56
mZIndex
=
Value
57
RaisePropertyChanged(
"
ZIndex
"
)
58
End
Set
59
End Property
60
61
'
62
'
Background As Brush
63
'
64
Private
mBackground
As
Brush
=
Brushes.LightBlue
65
Public
Property
Background()
As
Brush
66
Get
67
Return
mBackground
68
End
Get
69
Set
(
ByVal
Value
As
Brush)
70
mBackground
=
Value
71
RaisePropertyChanged(
"
Background
"
)
72
End
Set
73
End Property
74
75
End Class

 

跨界的属性也只是ZIndex而已,如果实在没办法,就这样吧,唉唉。

 

MainWindowViewModel

 
1
Imports
System.Collections.ObjectModel
2
3
Public
Class
MainWindowViewModel
4
Inherits
NotificationObject
5
'
6
'
NodeList As ObservableCollection(Of Node)
7
'
8
Private
mNodeList
As
ObservableCollection(
Of
Node)
9
Public
Property
NodeList()
As
ObservableCollection(
Of
Node)
10
Get
11
If
mNodeList
Is
Nothing
Then
12
mNodeList
=
New
ObservableCollection(
Of
Node)
13
End
If
14
Return
mNodeList
15
End
Get
16
Set
(
ByVal
Value
As
ObservableCollection(
Of
Node))
17
mNodeList
=
Value
18
RaisePropertyChanged(
"
NodeList
"
)
19
End
Set
20
End Property
21
22
Public
Sub
New
()
23
Dim
newNode
As
New
Node
24
newNode.Text
=
"
新主题
"
25
newNode.Top
=
100
26
newNode.Left
=
50
27
newNode.ZIndex
=
0
28
newNode.Background
=
Brushes.LightCoral
29
NodeList.Add(newNode)
30
Dim
node2
As
New
Node
31
node2.Text
=
"
副本
"
32
node2.Left
=
200
33
node2.Top
=
100
34
node2.ZIndex
=
0
35
node2.Background
=
Brushes.Black
36
NodeList.Add(node2)
37
Dim
node3
As
New
Node
38
With
node3
39
.Text
=
"
副本
"
40
.Left
=
300
41
.Top
=
100
42
.ZIndex
=
0
43
.Background
=
Brushes.Black
44
End
With
45
46
NodeList.Add(node3)
47
End Sub
48
49
End Class
50

 

看看MainWindow的代码吧

先是Xaml

 
1
<
Window
x:Class
="MainWindow"
x:Name
="mainWindow"
2
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
4
xmlns:ct
="clr-namespace:AMindMapControls;assembly=AMindMapControls"
5
Title
="MainWindow"
Height
="350"
Width
="525"
>
6
<
Grid
Background
="Transparent"
>
7
<
ItemsControl
Name
="NodeLayer"
ItemsSource
="
{Binding NodeList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}
"
>
8
<
ItemsControl.Template
>
9
<
ControlTemplate
TargetType
="
{x:Type ItemsControl}
"
>
10
<
ItemsPresenter
/>
11
</
ControlTemplate
>
12
</
ItemsControl.Template
>
13
<
ItemsControl.ItemContainerStyle
>
14
<
Style
TargetType
="
{x:Type ContentPresenter}
"
>
15
<
Setter
Property
="Canvas.Left"
Value
="
{Binding Path=Left}
"
></
Setter
>
16
<
Setter
Property
="Canvas.Top"
Value
="
{Binding Path=Top}
"
></
Setter
>
17
<
Setter
Property
="Canvas.ZIndex"
Value
="
{Binding Path=ZIndex}
"
></
Setter
>
18
</
Style
>
19
</
ItemsControl.ItemContainerStyle
>
20
<
ItemsControl.ItemTemplate
>
21
<
DataTemplate
>
22
<
ct:ANode
x:Name
="Node"
Text
="
{Binding Text}
"
23
OnDragStart
="ANode_OnDragStart"
24
OnDragEnd
="ANode_OnDragEnd"
25
ZIndex
="
{Binding ZIndex, Mode=OneWayToSource}
"
26
BackgroundColor
="
{Binding Background}
"
27
>
28
29
</
ct:ANode
>
30
</
DataTemplate
>
31
</
ItemsControl.ItemTemplate
>
32
<
ItemsControl.ItemsPanel
>
33
<
ItemsPanelTemplate
>
34
<
Canvas
Name
="NodeCanvas"
Background
="Transparent"
35
MouseMove
="NodeCanvas_MouseMove"
36
MouseDown
="NodeCanvas_MouseDown"
>
37
</
Canvas
>
38
</
ItemsPanelTemplate
>
39
</
ItemsControl.ItemsPanel
>
40
</
ItemsControl
>
41
</
Grid
>
42
</
Window
>
43

Canvas是一个方便通过坐标来控制控件位置的容器,所以,像MindMap还是最好用Canvas

来实现,但是问题就来了,Canvas并不能绑定列表或表格形式的数据。而我们的Node是

列表形式的,也是为了方便存储。所以采用ItemsContorl来实现Canvas的列表数据绑定,

为什么要这么做呢,首先,从操作上看,ANode的个数不是固定的,而且会反复的增加和减少

如果自己管理ANode的增加和减少的话,将是不胜其烦的事情,而列表绑定,就变得非常轻松

了,只要对后台模型进行操作,即可实现UI层的对象的增添。也简化每个ANode对应后台的

绑定过程,像我这种懒人,简直是不二之选,哪怕打破UI和Model的松耦合,实际上,目前来看

处理有一个迂回的绑定(详见另一Post ),也没有其他的问题。

 

分解一下,MainWindow.Xaml

最外层Grid,背景被设置为Transparent,如果不设置任何背景色,将无法获得鼠标事件的支持。

我们还要拖动ANode。接下来是ItemsContorl,对于ItemsContorl和Canvas的关系,当然还有

ANode,请参考另三个Pos (2)(3)

 

好吧,MainWindow.Xaml没什么好讲的了。

看看后台

 
1
Imports
AMindMapControls
2
3
Class
MainWindow
4
Private
vm
As
New
MainWindowViewModel
5
6
Public
Sub
New
()
7
8
'
此调用是设计器所必需的。
9
InitializeComponent()
10
11
'
在 InitializeComponent() 调用之后添加任何初始化。
12
Me
.DataContext
=
vm
13
End Sub
14
15
#Region
" 拖放 "
16
Private
DragPoint
As
Point
17
Private
DragNode
As
ANode
18
19
Private
Sub
NodeCanvas_MouseMove(
ByVal
sender
As
System.Object,
ByVal
e
As
System.Windows.Input.MouseEventArgs)
20
If
DragNode
Is
Nothing
Then
Exit Sub
21
With
CType
(DragNode.DataContext, Node)
22
.Left
=
e.GetPosition(sender).X
-
DragPoint.X
23
.Top
=
e.GetPosition(sender).Y
-
DragPoint.Y
24
End
With
25
End Sub
26
27
Private
Sub
ANode_OnDragStart(
ByVal
sender
As
AMindMapControls.ANode,
ByVal
p
As
Point)
28
DragPoint
=
p
29
DragNode
=
sender
30
End Sub
31
32
Private
Sub
ANode_OnDragEnd(
ByVal
sender
As
AMindMapControls.ANode)
33
DragNode
=
Nothing
34
End Sub
35
#End Region
36
37
Private
Sub
NodeCanvas_MouseDown(
ByVal
sender
As
System.Object,
ByVal
e
As
System.Windows.Input.MouseButtonEventArgs)
38
ANode.SetAllNormal()
39
End Sub
40
41
End Class
42

Wpf的事件传递 真是太复杂了,所以,用OnDragStart和OnDragEnd事件来标记拖拽的开始

和结束,并且在界面空白处按下鼠标,取消所有ANode的活动状态,测试完成,效果很理想

 

下期预告,为 脑图节点,建立后台模型和对模型进行基本管理。其实Node就是模型。

转载于:https://www.cnblogs.com/allofalan/archive/2012/04/13/2445566.html

你可能感兴趣的文章
DataTable行列转换
查看>>
Java豆瓣电影爬虫——使用Word2Vec分析电影短评数据
查看>>
特殊符号编码
查看>>
cookie 与 session 组件
查看>>
instanceof
查看>>
activity的四种模式
查看>>
z-index
查看>>
git 和github
查看>>
Vue的路由
查看>>
RESTful API
查看>>
dependencies与devDependencies之间的区别
查看>>
【分块】hdu5057 Argestes and Sequence
查看>>
【set】bzoj3715 [PA2014]Lustra
查看>>
反射机制(二)
查看>>
getGeneratedKeys()返回自增主键值
查看>>
随机数创建点shp文件
查看>>
TOJ 2710: 过河 路径压缩
查看>>
javascript中null与undefined的区别
查看>>
mysql之select(二)
查看>>
万能分页存储过程
查看>>