Common

EnumUtils

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
87
88
89
90
91
92
93
public static class EnumUtils
{
public static string GetDescription(this System.Enum obj)
{
string objName = obj.ToString();
Type t = obj.GetType();
FieldInfo fi = t.GetField(objName);
DescriptionAttribute[] descriptionAttributes =
(DescriptionAttribute[])fi.GetCustomAttributes(
typeof(DescriptionAttribute), false);
if (descriptionAttributes.Length > 0)
return descriptionAttributes[0].Description;
return null;
}

public static string GetTagValue(this System.Enum enumObj, TagAttributeKey tagAttributeKey)
{
string enumObjVal = enumObj.ToString();
Type enumType = enumObj.GetType();
FieldInfo fi = enumType.GetField(enumObjVal);
EnumItemTagAttribute[] tagAttributes =
(EnumItemTagAttribute[])fi.GetCustomAttributes(
typeof(EnumItemTagAttribute), false);
if (tagAttributes.Length > 0)
foreach (var tag in tagAttributes)
if (tag.Key == tagAttributeKey)
return tag.Value;
return null;
}

public static List<string> GetTagValues(this System.Enum enumObj, TagAttributeKey tagAttributeKey)
{
List<string> tags = new List<string>();
string enumObjVal = enumObj.ToString();
Type enumType = enumObj.GetType();
FieldInfo fi = enumType.GetField(enumObjVal);
EnumItemTagAttribute[] tagAttributes =
(EnumItemTagAttribute[])fi.GetCustomAttributes(
typeof(EnumItemTagAttribute), false);
if (tagAttributes.Length > 0)
foreach (var tag in tagAttributes)
if (tag.Key == tagAttributeKey)
tags.Add(tag.Value);
return tags;
}

public static T GetEnumByDescription<T>(string description) where T : struct, System.Enum
{
T enumObj = default(T);
foreach (T enumField in System.Enum.GetValues(typeof(T)))
{
string desc = GetDescription(enumField);
if (desc.Equals(description))
enumObj = enumField;
}
return enumObj;
}

public static List<T> GetEnumItems<T>() where T : struct, System.Enum
{
List<T> values = new List<T>();
foreach (T enumField in System.Enum.GetValues(typeof(T)))
values.Add(enumField);
return values;
}
}

public enum TagAttributeKey
{
Unknown,
DataType,
FileFilter
}

[AttributeUsage(AttributeTargets.Field, AllowMultiple =true)]
public class EnumItemTagAttribute:Attribute
{
private TagAttributeKey _key = TagAttributeKey.Unknown;
public TagAttributeKey Key
{
get { return _key; }
}
private string _value;
public string Value
{
get { return _value; }
}
public EnumItemTagAttribute(TagAttributeKey key, string val)
{
_key = key;
_value = val;
}
}

DialogUtils

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
public class DialogUtils
{
public static void OpenExplorer(string path)
{
try
{
Process.Start("explorer.exe", path);
}
catch (Exception ex)
{
ProMessageUtils.ShowDialogErr($"文件资源管理器报错:{ex.Message}");
AppLogger.Err("文件资源管理器报错!", ex);
}
}

public static string SelectFile(string filter, string title = "选择文件")
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Title = title;
openFileDialog.Filter = filter;
if (openFileDialog.ShowDialog() == DialogResult.OK)
return openFileDialog.FileName;
else
return null;
}

public static string SelectFolder(string title = "选择文件夹")
{
FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
folderBrowserDialog.Description = title;
if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
{
string selectedPath = folderBrowserDialog.SelectedPath;
if (selectedPath.Last() != Path.DirectorySeparatorChar)
selectedPath += Path.DirectorySeparatorChar;
return selectedPath;
}
else
return null;
}
}

WPF - UIUtils

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
public class UiUtils
{
private static DispatcherOperationCallback
exitFrameCallback = new DispatcherOperationCallback(ExitFrame);
/// <summary>
/// 刷新界面
/// </summary>
public static void DoEvents()
{
DispatcherFrame nestedFrame = new DispatcherFrame();
DispatcherOperation exitOperation =
Dispatcher.CurrentDispatcher.BeginInvoke(
DispatcherPriority.Background,
exitFrameCallback, nestedFrame);
Dispatcher.PushFrame(nestedFrame);

if (exitOperation.Status != DispatcherOperationStatus.Completed)
{
exitOperation.Abort();
}
}
/// <summary>
/// 调用UI线程执行
/// </summary>
/// <param name="action">等待执行方法</param>
public static void Invoke(Action action)
{
System.Windows.Application.Current.Dispatcher.Invoke(action);
}
/// <summary>
/// 获取窗体所在屏幕
/// </summary>
/// <param name="window">窗体</param>
/// <returns>屏幕</returns>
public static Screen GetScreen(Window window)
{
PresentationSource source = PresentationSource.FromVisual(window);
Visual visual = source.RootVisual;
var screen = System.Windows.Forms.Screen.FromHandle(new WindowInteropHelper(window).Handle);
return screen;
}
/// <summary>
/// 获取窗体所在屏幕工作区(不包含任务栏)大小
/// </summary>
/// <param name="window">窗体</param>
/// <returns>工作区大小</returns>
public static Rect GetScreenWorkingAreaRect(Window window)
{
var scale = PresentationSource.FromVisual(window).CompositionTarget.TransformToDevice.M11;
Screen screen = GetScreen(window);
Rect rect = new Rect(0, 0, screen.WorkingArea.Width / scale, screen.WorkingArea.Height / scale);
return rect;
}
/// <summary>
/// 最大化窗体
/// </summary>
/// <param name="window">窗体</param>
public static void MaximizeWindow(Window window)
{
if (window.WindowState == WindowState.Maximized)
{
window.WindowState = WindowState.Normal;
//var bitmap = new BitmapImage(new Uri("pack://application:,,,/Shexo;component/res/PNG_Maximize_ZoomIn.png"));
//image.Source = bitmap;
}
else
{
Rect rect = UiUtils.GetScreenWorkingAreaRect(window);
window.MaxHeight = rect.Height;
window.WindowState = WindowState.Maximized;
//var bitmap = new BitmapImage(new Uri("pack://application:,,,/Shexo;component/res/PNG_Maximize_ZoomOut.png"));
//image.Source = bitmap;
}
}
/// <summary>
/// 窗体居中于工作区
/// </summary>
/// <param name="window">窗体</param>
public static void Centralize(Window window)
{
Rect rect = GetScreenWorkingAreaRect(window);
window.Left = (rect.Width - window.Width) / 2;
window.Top = (rect.Height - window.Height) / 2;
}
/// <summary>
/// 窗体居中于拥有者
/// </summary>
/// <param name="window">窗体</param>
public static void CentralizeOwner(Window window)
{
Window owner = window.Owner;
Rect rect = new Rect(owner.Left, owner.Top, owner.Width, owner.Height);
window.Left = (rect.Width - window.Width) / 2 + owner.Left;
window.Top = (rect.Height - window.Height) / 2 + owner.Top;
}
/// <summary>
/// 注册窗体拖动事件
/// </summary>
/// <param name="frameworkElement">窗体控件</param>
public static void RegisterWindowMoveEvent(FrameworkElement frameworkElement)
{
frameworkElement.PreviewMouseMove += MoveWindow_PreviewMouseMove;
}

private static object ExitFrame(object state)
{
DispatcherFrame frame = state as DispatcherFrame;
frame.Continue = false;
return null;
}
private static void MoveWindow_PreviewMouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
if (Mouse.LeftButton != MouseButtonState.Pressed)
return;
FrameworkElement frameworkElement = sender as FrameworkElement;
DependencyObject parent = VisualTreeHelper.GetParent(frameworkElement);
while (parent != null && !(parent is Window))
parent = VisualTreeHelper.GetParent(parent);
if (parent == null)
return;
Window window = parent as Window;

window.DragMove();
}
}

TreeUtils

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
public interface ITreeViewItem
{
string Id { get; set; }
string Fid { get; set; }
object Data { get; set; }
string Name { get; set; }
string IconUrl { get; set; }
string Tag { get; set; }
bool IsExpanded { get; set; }
bool IsSelected { get; set; }
ITreeViewItem Clone();
}

public class TreeViewItemBase : ViewModelBase, ITreeViewItem
{
private string _id;
public virtual string Id
{
get { return _id; }
set { SetProperty(ref _id, value); }
}

private string _fid;
public virtual string Fid
{
get { return _fid; }
set { SetProperty(ref _fid, value); }
}

private object _data;
public virtual object Data
{
get { return _data; }
set { SetProperty(ref _data, value); }
}

private string _name;
public virtual string Name
{
get { return _name; }
set { SetProperty(ref _name, value); }
}

private string _iconUrl;
public virtual string IconUrl
{
get { return _iconUrl; }
set { SetProperty(ref _iconUrl, value); }
}

private string _tag;
public virtual string Tag
{
get { return _tag; }
set { SetProperty(ref _tag, value); }
}

private bool _isExpanded = true;
public virtual bool IsExpanded
{
get { return _isExpanded; }
set { SetProperty(ref _isExpanded, value); }
}

private bool _isSelected;
public virtual bool IsSelected
{
get { return _isSelected; }
set { SetProperty(ref _isSelected, value); }
}

//private ObservableCollection<ITreeViewItem> _childItems = new ObservableCollection<ITreeViewItem>();
//public virtual ObservableCollection<ITreeViewItem> ChildItems
//{
// get { return _childItems; }
// set { SetProperty(ref _childItems, value); }
//}

public virtual ITreeViewItem Clone()
{
Type type = this.GetType();
Type listType = typeof(List<>).MakeGenericType(type);
ITreeViewItem clone = Activator.CreateInstance(type) as ITreeViewItem;
if (clone == null)
return null;
foreach (var item in type.GetProperties())
{
if (item.PropertyType.Equals(listType))
{
IList childItems = (IList)item.GetValue(this);
if (childItems == null)
continue;
IList cloneChildItems = (IList)Activator.CreateInstance(listType);
foreach (var childItem in childItems)
cloneChildItems.Add(((ITreeViewItem)childItem).Clone());
item.SetValue(clone, cloneChildItems);
}
else
{
object value = item.GetValue(this);
item.SetValue(clone, value);
}
}
return clone;
}

public virtual ITreeViewItem SearchName(string searchText)
{
bool search = false;
ITreeViewItem clone = this.Clone();
search = SearchItemRec(clone, searchText);
return search ? clone : null;
}

private bool SearchItemRec(ITreeViewItem treeViewItem, string searchText)
{
Type type = treeViewItem.GetType();
Type listType = typeof(List<>).MakeGenericType(type);
foreach (var propertyItem in type.GetProperties())
{
if (!propertyItem.PropertyType.Equals(listType))
continue;
IList childItems = (IList)propertyItem.GetValue(treeViewItem);
if (childItems != null && childItems.Count > 0)
{
List<ITreeViewItem> rm = new List<ITreeViewItem>();
foreach (ITreeViewItem childItem in childItems)
{
bool res = SearchItemRec(childItem, searchText);
if (!res)
rm.Add(childItem);
}
foreach (var item in rm)
childItems.Remove(item);
}
if (childItems.Count > 0 || treeViewItem.Name.Contains(searchText))
{
//dataCatalogItem.IsExpanded = true;
return true;
}
}
return false;
}

public virtual ITreeViewItem Search(Dictionary<string, string> searchData, bool isContains)
{
bool search = false;
ITreeViewItem clone = this.Clone();
search = SearchItemRec(clone, searchData, isContains);
return search ? clone : null;
}
public virtual ITreeViewItem Search(Dictionary<string, List<string>> searchData, bool isContains)
{
bool search = false;
ITreeViewItem clone = this.Clone();
search = SearchItemRec(clone, searchData, isContains);
return search ? clone : null;
}

private bool SearchItemRec(ITreeViewItem treeViewItem, Dictionary<string, string> searchData, bool isContains)
{
Type type = treeViewItem.GetType();
Type listType = typeof(List<>).MakeGenericType(type);
foreach (var propertyItem in type.GetProperties())
{
if (!propertyItem.PropertyType.Equals(listType))
continue;
IList childItems = (IList)propertyItem.GetValue(treeViewItem);
if (childItems != null && childItems.Count > 0)
{
List<ITreeViewItem> rm = new List<ITreeViewItem>();
foreach (ITreeViewItem item in childItems)
{
bool res = SearchItemRec(item, searchData, isContains);
if (!res)
rm.Add(item);
}
foreach (var item in rm)
{
childItems.Remove(item);
}
}
if (childItems.Count > 0)
return true;
foreach (var item in searchData)
{
PropertyInfo propertyInfo = type.GetProperty(item.Key);
if (propertyInfo == null)
return false;
object value = propertyInfo.GetValue(treeViewItem);
if (value == null)
return false;
if (isContains)
{
if (!value.ToString().ToLower().Contains(item.Value.ToLower()))
return false;
}
else
{
if (value.ToString().ToLower() != item.Value.ToLower())
return false;
}
}
//dataCatalogItem.IsExpanded = true;
return true;
}

return false;
}
private bool SearchItemRec(ITreeViewItem treeViewItem, Dictionary<string, List<string>> searchData, bool isContains)
{
Type type = treeViewItem.GetType();
Type listType = typeof(List<>).MakeGenericType(type);
foreach (var propertyItem in type.GetProperties())
{
if (!propertyItem.PropertyType.Equals(listType))
continue;
IList childItems = (IList)propertyItem.GetValue(treeViewItem);
if (childItems != null && childItems.Count > 0)
{
List<ITreeViewItem> rm = new List<ITreeViewItem>();
foreach (ITreeViewItem item in childItems)
{
bool res = SearchItemRec(item, searchData, isContains);
if (!res)
rm.Add(item);
}
foreach (var item in rm)
{
childItems.Remove(item);
}
}
if (childItems.Count > 0)
return true;
foreach (var item in searchData)
{
PropertyInfo propertyInfo = type.GetProperty(item.Key);
if (propertyInfo == null)
return false;
object value = propertyInfo.GetValue(treeViewItem);
if (value == null)
return false;
if (isContains)
{
bool isEff = false;
foreach (var val in item.Value)
{
if(value.ToString().ToLower().Contains(val.ToLower()))
isEff = true;
}
if (!isEff)
return false;
}
else
{
bool isEff = false;
foreach (var val in item.Value)
{
if (value.ToString().ToLower() == val.ToLower())
isEff = true;
}
if (!isEff)
return false;
}
}
//dataCatalogItem.IsExpanded = true;
return true;
}

return false;
}

}

FileUtils

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
public class FileUtils
{
public static string Read(string filePath)
{
StreamReader sr = null;
string readText = string.Empty;
try
{
sr = new StreamReader(filePath);
readText = sr.ReadToEnd();
}
catch (Exception ex)
{
AppLogger.Err("读取文本文件内容失败!", ex);
}
finally { if (sr != null) try { sr.Close(); } catch { } }
return readText;
}

public static bool Write(string filePath, string text)
{
string folderPath = Path.GetDirectoryName(filePath);
if(folderPath!=null && !Directory.Exists(folderPath))
Directory.CreateDirectory(folderPath);
StreamWriter sw = null;
try
{
sw = new StreamWriter(filePath);
sw.Write(text);
sw.Flush();
return true;
}
catch(Exception ex)
{
AppLogger.Err("写入文本文件内容失败!", ex);
return false;
}
finally { if (sw != null) try { sw.Close(); } catch { } }
}

public static bool Append(string txtFilePath, string content)
{
string folderPath = Path.GetDirectoryName(txtFilePath);
if (folderPath != null && !Directory.Exists(folderPath))
Directory.CreateDirectory(folderPath);
FileStream fileStream = null;
StreamWriter streamWriter = null;
try
{
if (File.Exists(txtFilePath))
{
streamWriter = File.AppendText(txtFilePath);
}
else
{
fileStream = new FileStream(txtFilePath, FileMode.OpenOrCreate);
streamWriter = new StreamWriter(fileStream);
}
streamWriter.Write(content);
streamWriter.Flush();
return true;
}
catch (Exception ex)
{
AppLogger.Err("写入文本文件内容失败!", ex);
return false;
}
finally
{
if (streamWriter != null)
{
streamWriter.Close();
}
if (fileStream != null)
{
fileStream.Close();
}
}
}

public static bool ByteToFile(byte[] byteArray, string fileName)
{
bool result = false;
try
{
if (!Directory.Exists(Path.GetDirectoryName(fileName)))
Directory.CreateDirectory(Path.GetDirectoryName(fileName));
using (FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Write))
{
fs.Write(byteArray, 0, byteArray.Length);
result = true;
}
}
catch
{
result = false;
}
return result;
}

public static bool CopyFile(string sourceFilePath, string targetFilePath)
{
try
{
File.Copy(sourceFilePath, targetFilePath, true);
return true;
}
catch (Exception ex)
{
AppLogger.Err($"无法复制文件:{sourceFilePath}", ex);
return false;
}
}
}

FolderUtils

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
public class FolderUtils
{
public static bool CopyFolder(string sourceFolder, string targetFolder)
{
try
{
if (!Directory.Exists(targetFolder))
Directory.CreateDirectory(targetFolder);
foreach (var file in Directory.GetFiles(sourceFolder))
{
string targetFilePath = Path.Combine(targetFolder, Path.GetFileName(file));
File.Copy(file, targetFilePath, true);
}
foreach (var subFolder in Directory.GetDirectories(sourceFolder))
{
string targetSubFolder = Path.Combine(targetFolder, Path.GetFileName(subFolder));
bool copy = CopyFolder(subFolder, targetSubFolder);
if(!copy) return false;
}
return true;
}
catch (Exception ex)
{
AppLogger.Err("目录拷贝失败!\r\n源:" + sourceFolder + "\r\n目标:" + targetFolder, ex);
}
return false;
}
}

PathUtils

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
public class PathUtils
{
public static string NewFilePath(string path, int mode)
{
string folder = Path.GetDirectoryName(path);
if (folder[folder.Length - 1] != Path.DirectorySeparatorChar)
folder += Path.DirectorySeparatorChar;
string fileName = Path.GetFileNameWithoutExtension(path);
string extension = Path.GetExtension(path);
int tag = 0;
while (File.Exists(path))
{
if(mode == 0)
{
path = $"{folder}{fileName} ({++tag}){extension}";
}
else if(mode == 1)
{
path = $"{folder}{fileName}_{++tag}{extension}";
}
else
mode = 0;
}
return path;
}
public static string ConvertValidPath(string path)
{
//\/:*?"<>|
path = path.Replace("/", "_");
path = path.Replace(":", "_");
path = path.Replace("*", "_");
path = path.Replace("?", "_");
path = path.Replace("\"", "_");
path = path.Replace("<", "_");
path = path.Replace(">", "_");
path = path.Replace("|", "_");
return path;
}
public static string ConvertValidFileName(string fileName)
{
//\/:*?"<>|
fileName = fileName.Replace("\\", "_");
fileName = fileName.Replace("/", "_");
fileName = fileName.Replace(":", "_");
fileName = fileName.Replace("*", "_");
fileName = fileName.Replace("?", "_");
fileName = fileName.Replace("\"", "_");
fileName = fileName.Replace("<", "_");
fileName = fileName.Replace(">", "_");
fileName = fileName.Replace("|", "_");
return fileName;
}
}

RegexUtils

1
2
3
4
5
6
7
8
9
10
11
12
13
public class RegexUtils
{
public static bool IsSheetDesignation(string str)
{
Regex regex = new Regex("[A-V][0-6][0-9][A-H][0-9]{6}");
return regex.IsMatch(str);
}
public static bool IsValidPath(string path)
{
string pattern = @"[\\/:*?""<>|]";
return !Regex.IsMatch(path, pattern);
}
}

SerializationUtils

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
public class SerializationUtils
{
public static void Serialization<T>(T obj, string saveFilePath)
{
string dirName = Path.GetDirectoryName(saveFilePath);
if (!Directory.Exists(dirName))
Directory.CreateDirectory(dirName);
using (FileStream fileStream = new FileStream(saveFilePath, FileMode.Create))
{
try
{
BinaryFormatter b = new BinaryFormatter();
b.Serialize(fileStream, obj);
}
catch (Exception ex)
{
throw ex;
}
finally
{
fileStream.Close();
}
}
}
public static T Deserialization<T>(string filePath)
{
T obj = default(T);
if (!File.Exists(filePath))
return obj;
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
try
{
BinaryFormatter b = new BinaryFormatter();
obj = (T)b.Deserialize(fileStream);
}
catch (Exception ex)
{
throw ex;
}
finally
{
fileStream.Close();
}
}
return obj;
}
}

TextBoxUtils

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
public class TextBoxUtils
{
/// <summary>
/// 设置TextBox输入必须为小数
/// </summary>
/// <param name="textBox">TextBox控件</param>
public static void SetInputMustDecimal(TextBox textBox)
{
InputMethod.SetIsInputMethodEnabled(textBox, false);
textBox.PreviewTextInput += (object sender, TextCompositionEventArgs e) =>
{
TextBox textBox = sender as TextBox;
if (textBox == null)
return;
if (e.Text == ".")
{
if (textBox.Text.Length == 0 || textBox.Text.Contains("."))
e.Handled = true;
}
else
{
bool rst = int.TryParse(e.Text, out int i);
e.Handled = !rst;
}
};
textBox.TextChanged += (object sender, TextChangedEventArgs e) =>
{
TextBox textBox = sender as TextBox;
if (textBox == null)
return;
bool rst = double.TryParse(textBox.Text, out double d);
if (!rst)
{
if (e.Changes.Count < 1)
return;
int offset = e.Changes.ElementAt(0).Offset;
textBox.Text = textBox.Text.Remove(offset);
}
};
}
/// <summary>
/// 设置TextBox输入必须为整数
/// </summary>
/// <param name="textBox">TextBox控件</param>
public static void SetInputMustInt(TextBox textBox)
{
InputMethod.SetIsInputMethodEnabled(textBox, false);
textBox.PreviewTextInput += (object sender, TextCompositionEventArgs e) =>
{
TextBox textBox = sender as TextBox;
if (textBox == null)
return;
bool rst = int.TryParse(e.Text, out int i);
e.Handled = !rst;
};
textBox.TextChanged += (object sender, TextChangedEventArgs e) =>
{
TextBox textBox = sender as TextBox;
if (textBox == null)
return;
bool rst = int.TryParse(textBox.Text, out int i);
if (!rst)
{
if (e.Changes.Count < 1)
return;
int offset = e.Changes.ElementAt(0).Offset;
textBox.Text = textBox.Text.Remove(offset);
}
};
}
}

DataTableUtils

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
public class DataTableUtils
{
public static DataTable FromCSV(string csvFilePath, string separator = ",")
{
DataTable dt = new DataTable();
FileStream fs = null;
StreamReader sr =null;
try
{
fs = new FileStream(csvFilePath, FileMode.Open, FileAccess.Read);
sr = new StreamReader(fs, Encoding.UTF8);
string strLine = null;
string[] arrayLine = null;
bool isFirst = true;
while (!string.IsNullOrEmpty(strLine = sr.ReadLine()))
{
strLine = strLine.Trim();
arrayLine = strLine.Split(separator.ToCharArray());
int dtColumns = arrayLine.Length;
if (isFirst)
{
for (int i = 0; i < dtColumns; i++)
{
dt.Columns.Add(arrayLine[i].Trim('\"'));
}
isFirst = false;
}
else
{
DataRow dataRow = dt.NewRow();//新建一行
for (int j = 0; j < dtColumns; j++)
{
dataRow[j] = arrayLine[j].Trim('\"');
}
dt.Rows.Add(dataRow);
}
}
}
catch (Exception ex)
{
AppLogger.Err("读取csv文件失败!", ex);
return null;
}
finally
{
if (sr != null) try { sr.Close(); } catch { }
if (fs != null) try { fs.Close(); } catch { }
}
return dt;
}
public static void ToCSV(string csvFilePath, DataTable dt)
{
FileStream fs = null;
StreamWriter sw = null;
string data = null;
try
{
if (File.Exists(csvFilePath))
{
System.Windows.MessageBoxResult messageBoxResult = ProMessageUtils.ShowDialog(
"文件已经存在,是否覆盖?\r\n【是】- 覆盖并接入内容;\r\n" +
"【否】- 不覆盖,追加内容;\r\n【取消】- 退出。", "提示",
System.Windows.MessageBoxButton.YesNoCancel, System.Windows.MessageBoxImage.Question);
if (messageBoxResult == System.Windows.MessageBoxResult.Yes)
{
fs = new FileStream(csvFilePath, FileMode.Create, FileAccess.Write);
sw = new StreamWriter(fs, Encoding.UTF8);
//写出列名称
for (int i = 0; i < dt.Columns.Count; i++)
{
data += dt.Columns[i].ColumnName.ToString();
if (i < dt.Columns.Count - 1)
{
data += ",";//中间用,隔开
}
}
sw.WriteLine(data);
}
else if (messageBoxResult == System.Windows.MessageBoxResult.No)
{
fs = new FileStream(csvFilePath, FileMode.Append, FileAccess.Write);
sw = new StreamWriter(fs, Encoding.UTF8);
}
}
for (int i = 0; i < dt.Rows.Count; i++)
{
data = null;
for (int j = 0; j < dt.Columns.Count; j++)
{
data += dt.Rows[i][j].ToString();
if (j < dt.Columns.Count - 1)
{
data += ",";//中间用,隔开
}
}
sw.WriteLine(data);
}
}
catch(Exception ex)
{
AppLogger.Err("写入csv文件失败!", ex);
}
finally
{
if (sw != null) try { sw.Close(); } catch { }
if (fs != null) try { fs.Close(); } catch { }
}
}
public static DataTable FromExcel(string excelFilePath, string sheetName)
{
DataTable dataTable = new DataTable(sheetName);
IWorkbook wb = GetWorkbook(excelFilePath);
if (wb == null)
return null;
ISheet ws = wb.GetSheet(sheetName);
if (ws.LastRowNum < 1)
return dataTable;
int rowNum = ws.LastRowNum + 1;
int colNum = ws.GetRow(0).LastCellNum;
for (int i = 0; i < colNum; i++)
{
ICell cell = ws.GetRow(0)?.GetCell(i);
string val = cell?.StringCellValue;
if (val == null)
val = "未知列名";
string tmpVal = val;
int tag = 1;
while (dataTable.Columns.Contains(tmpVal))
tmpVal = val + "_" + tag++;
dataTable.Columns.Add(tmpVal);
}
if (rowNum > 1)
{
for (int i = 1; i < rowNum; i++)
{
DataRow dataRow = dataTable.NewRow();
for (int j = 0; j < colNum; j++)
{
IRow row = ws.GetRow(i);
ICell cell = row.GetCell(j);
dataRow[j] = GetValue(cell);
}
dataTable.Rows.Add(dataRow);
}
}
return dataTable;
}
public static DataSet FromExcel(string excelFilePath)
{
IWorkbook wb = GetWorkbook(excelFilePath);
if(wb == null)
return null;
DataSet ds = new DataSet();
for (int i = 0; i < wb.NumberOfSheets; i++)
{
ISheet sheet = wb.GetSheetAt(i);
ds.Tables.Add(FromExcel(excelFilePath, sheet.SheetName));
}
return ds;
}
public static bool ToExcel(string excelFilePath, DataTable dataTable)
{
IWorkbook wb = GetWorkbook(excelFilePath);
if (wb == null)
return false;
ISheet ws = wb.CreateSheet(dataTable.TableName);
IRow firstrow = ws.CreateRow(0);
for (int c = 0; c <= dataTable.Columns.Count - 1; c++)
firstrow.CreateCell(c).SetCellValue(dataTable.Columns[c].ColumnName);
for (int i = 0; i <= dataTable.Rows.Count - 1; i++)
{
IRow dataRow = ws.CreateRow(i + 1);
for (int j = 0; j <= dataTable.Columns.Count - 1; j++)
{
ICell cell = dataRow.CreateCell(j);
cell.SetCellValue(dataTable.Rows[i][j]?.ToString());
}
}
using (FileStream fs = File.OpenWrite(excelFilePath))
{
try
{
wb.Write(fs);
return true;
}
catch(Exception ex)
{
AppLogger.Err("写入Excel失败!", ex);
return false;
}
finally { if (fs != null) try { fs.Close(); } catch { } }
}
}
public static bool ToExcel(string excelFilePath, DataSet dataSet)
{
IWorkbook wb = GetWorkbook(excelFilePath);
if(wb == null)
return false;
foreach (DataTable dataTable in dataSet.Tables)
{
ISheet ws = wb.CreateSheet(dataTable.TableName);
IRow firstrow = ws.CreateRow(0);
for (int c = 0; c <= dataTable.Columns.Count - 1; c++)
firstrow.CreateCell(c).SetCellValue(dataTable.Columns[c].ColumnName);
for (int i = 1; i <= dataTable.Rows.Count - 1; i++)
{
IRow dataRow = ws.CreateRow(i);
for (int j = 0; j <= dataTable.Columns.Count - 1; j++)
{
ICell cell = dataRow.CreateCell(j);
cell.SetCellValue(dataTable.Rows[i][j]?.ToString());
}
}
}
using (FileStream fs = File.OpenWrite(excelFilePath))
{
try
{
wb.Write(fs);
return true;
}
catch(Exception ex)
{
AppLogger.Err("写入Excel失败!", ex);
return false;
}
finally { if (fs != null) try { fs.Close(); } catch { } }
}
}

static IWorkbook GetWorkbook(string excelFilePath)
{
string extension = Path.GetExtension(excelFilePath);
IWorkbook wb = null;
FileStream fs = null;
try
{
if (!File.Exists(excelFilePath))
{
if (extension == ".xlsx" || extension == "xlsx")
wb = new XSSFWorkbook();
else if (extension == ".xls" || extension == "xls")
wb = new HSSFWorkbook();
else
{
ProMessageUtils.ShowDialog($"错误文件类型{extension}!");
return null;
}
}
else
{
fs = File.Open(excelFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
if (extension == ".xlsx" || extension == "xlsx")
wb = new XSSFWorkbook(fs);
else if (extension == ".xls" || extension == "xls")
wb = new HSSFWorkbook(fs);
else
{
ProMessageUtils.ShowDialog($"错误文件类型{extension}!");
return null;
}
}
//wb.Write(fs);
return wb;
}
catch (Exception ex)
{
AppLogger.Err("读取Excel文件失败!", ex);
return null;
}
finally { if (fs != null) try { fs.Close(); } catch { } }
}
static object GetValue(ICell cell)
{
if (cell == null)
return null;
switch (cell.CellType)
{
case CellType.Blank: //BLANK:
return null;
case CellType.Boolean: //BOOLEAN:
return cell.BooleanCellValue;
case CellType.Numeric: //NUMERIC:
return cell.NumericCellValue;
case CellType.String: //STRING:
return cell.StringCellValue;
case CellType.Error: //ERROR:
return cell.ErrorCellValue;
case CellType.Formula: //FORMULA:
default:
return "=" + cell.CellFormula;
}
}
}

EncryptionUtils

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
public class EncryptionUtils
{
static string _AES_SECRET_KEY = "9FCA07E906FB465EAF42558CB1A2F3E3";
// 加密字符串
public static string AesEncrypt(string plaintext)
{
if (plaintext == null) return null;
// 将密钥转换为字节数组
byte[] keyBytes = Encoding.UTF8.GetBytes(_AES_SECRET_KEY);
using (System.Security.Cryptography.Aes aes = System.Security.Cryptography.Aes.Create())
{
aes.Key = keyBytes;
aes.GenerateIV();
// 创建加密器
System.Security.Cryptography.ICryptoTransform encryptor = aes.CreateEncryptor();
// 将明文转换为字节数组
byte[] plaintextBytes = Encoding.UTF8.GetBytes(plaintext);
// 加密明文
byte[] ciphertextBytes = encryptor.TransformFinalBlock(plaintextBytes, 0, plaintextBytes.Length);
// 将密文和IV合并
byte[] combinedBytes = new byte[aes.IV.Length + ciphertextBytes.Length];
Array.Copy(aes.IV, 0, combinedBytes, 0, aes.IV.Length);
Array.Copy(ciphertextBytes, 0, combinedBytes, aes.IV.Length, ciphertextBytes.Length);
// 返回Base64编码的密文
return Convert.ToBase64String(combinedBytes);
}
}

// 解密字符串
public static string AesDecrypt(string ciphertext)
{
if(ciphertext == null) return null;
// 将密钥转换为字节数组
byte[] keyBytes = Encoding.UTF8.GetBytes(_AES_SECRET_KEY);
// 将Base64编码的密文转换为字节数组
byte[] combinedBytes = Convert.FromBase64String(ciphertext);
// 从密文中分离出IV和加密后的数据
byte[] ivBytes = new byte[16];
byte[] ciphertextBytes = new byte[combinedBytes.Length - ivBytes.Length];
Array.Copy(combinedBytes, ivBytes, ivBytes.Length);
Array.Copy(combinedBytes, ivBytes.Length, ciphertextBytes, 0, ciphertextBytes.Length);
using (System.Security.Cryptography.Aes aes = System.Security.Cryptography.Aes.Create())
{
aes.Key = keyBytes;
aes.IV = ivBytes;
// 创建解密器
System.Security.Cryptography.ICryptoTransform decryptor = aes.CreateDecryptor();
// 解密密文
byte[] plaintextBytes = decryptor.TransformFinalBlock(ciphertextBytes, 0, ciphertextBytes.Length);
// 将明文转换为字符串并返回
return Encoding.UTF8.GetString(plaintextBytes);
}
}

public static string SM2Encrypt(string publickey, string sourceData)
{
string ciphertext = SM2CryptoUtils.Encrypt(publickey, sourceData);
return ciphertext;
}

private class SM2CryptoUtils
{
#region 获取公钥私钥
/// <summary>
/// 获取公钥私钥
/// </summary>
/// <returns></returns>
public static SM2Model GetKey()
{
SM2 sm2 = SM2.Instance;
AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.GenerateKeyPair();
ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters)key.Private;
ECPublicKeyParameters ecpub = (ECPublicKeyParameters)key.Public;
BigInteger privateKey = ecpriv.D;
ECPoint publicKey = ecpub.Q;
SM2Model sM2Model = new SM2Model();
sM2Model.PrivateKey = Encoding.UTF8.GetString(Hex.Encode(privateKey.ToByteArray())).ToUpper();
sM2Model.PublicKey = Encoding.UTF8.GetString(Hex.Encode(publicKey.GetEncoded())).ToUpper();
return sM2Model;
}
#endregion

#region 加密
/// <summary>
/// 加密
/// </summary>
/// <param name="publickey">公钥</param>
/// <param name="sourceData">需要加密的值</param>
/// <returns>加密结果</returns>
public static string Encrypt(string publickey, string sourceData)
{
var data = Encrypt(Hex.Decode(publickey), Encoding.UTF8.GetBytes(sourceData));
return data;
}

/// <summary>
/// 加密
/// </summary>
/// <param name="publicKey">公钥</param>
/// <param name="data">需要加密的值</param>
/// <returns></returns>
public static String Encrypt(byte[] publicKey, byte[] data)
{
if (null == publicKey || publicKey.Length == 0)
{
return null;
}
if (data == null || data.Length == 0)
{
return null;
}

byte[] source = new byte[data.Length];
Array.Copy(data, 0, source, 0, data.Length);

Cipher cipher = new Cipher();
SM2 sm2 = SM2.Instance;

ECPoint userKey = sm2.ecc_curve.DecodePoint(publicKey);

ECPoint c1 = cipher.Init_enc(sm2, userKey);
cipher.Encrypt(source);

byte[] c3 = new byte[32];
cipher.Dofinal(c3);

String sc1 = Encoding.UTF8.GetString(Hex.Encode(c1.GetEncoded()));
String sc2 = Encoding.UTF8.GetString(Hex.Encode(source));
String sc3 = Encoding.UTF8.GetString(Hex.Encode(c3));

return (sc1 + sc3 + sc2).ToUpper();
}
#endregion

#region 解密

/// <summary>
///
/// </summary>
/// <param name="privateKey"></param>
/// <param name="encryptedData"></param>
/// <returns></returns>
public static string Decrypt(string privateKey, string encryptedData)
{
var data = Encoding.UTF8.GetString(Decrypt(Hex.Decode(privateKey), Hex.Decode(encryptedData)));
return data;
}
/// <summary>
/// 解密
/// </summary>
/// <param name="privateKey"></param>
/// <param name="encryptedData"></param>
/// <returns></returns>
public static byte[] Decrypt(byte[] privateKey, byte[] encryptedData)
{
if (null == privateKey || privateKey.Length == 0)
{
return null;
}
if (encryptedData == null || encryptedData.Length == 0)
{
return null;
}

String data = Encoding.UTF8.GetString(Hex.Encode(encryptedData));

byte[] c1Bytes = Hex.Decode(Encoding.UTF8.GetBytes(data.Substring(0, 130)));
int c2Len = encryptedData.Length - 97;
byte[] c2 = Hex.Decode(Encoding.UTF8.GetBytes(data.Substring(130, 2 * c2Len)));
byte[] c3 = Hex.Decode(Encoding.UTF8.GetBytes(data.Substring(130 + 2 * c2Len, 64)));

SM2 sm2 = SM2.Instance;
BigInteger userD = new BigInteger(1, privateKey);

//ECPoint c1 = sm2.ecc_curve.DecodePoint(c1Bytes);

ECPoint c1 = sm2.ecc_curve.DecodePoint(c1Bytes);
Cipher cipher = new Cipher();
cipher.Init_dec(userD, c1);
cipher.Decrypt(c2);
cipher.Dofinal(c3);

return c2;
}
#endregion

private class Cipher
{
private int ct;
private ECPoint p2;
private SM3Digest sm3keybase;
private SM3Digest sm3c3;
private byte[] key;
private byte keyOff;

public Cipher()
{
this.ct = 1;
this.key = new byte[32];
this.keyOff = 0;
}

public static byte[] byteConvert32Bytes(BigInteger n)
{
byte[] tmpd = null;
if (n == null)
{
return null;
}

if (n.ToByteArray().Length == 33)
{
tmpd = new byte[32];
Array.Copy(n.ToByteArray(), 1, tmpd, 0, 32);
}
else if (n.ToByteArray().Length == 32)
{
tmpd = n.ToByteArray();
}
else
{
tmpd = new byte[32];
for (int i = 0; i < 32 - n.ToByteArray().Length; i++)
{
tmpd[i] = 0;
}
Array.Copy(n.ToByteArray(), 0, tmpd, 32 - n.ToByteArray().Length, n.ToByteArray().Length);
}
return tmpd;
}

private void Reset()
{
this.sm3keybase = new SM3Digest();
this.sm3c3 = new SM3Digest();

byte[] p = byteConvert32Bytes(p2.Normalize().XCoord.ToBigInteger());
this.sm3keybase.BlockUpdate(p, 0, p.Length);
this.sm3c3.BlockUpdate(p, 0, p.Length);

p = byteConvert32Bytes(p2.Normalize().YCoord.ToBigInteger());
this.sm3keybase.BlockUpdate(p, 0, p.Length);
this.ct = 1;
NextKey();
}

private void NextKey()
{
SM3Digest sm3keycur = new SM3Digest(this.sm3keybase);
sm3keycur.Update((byte)(ct >> 24 & 0xff));
sm3keycur.Update((byte)(ct >> 16 & 0xff));
sm3keycur.Update((byte)(ct >> 8 & 0xff));
sm3keycur.Update((byte)(ct & 0xff));
sm3keycur.DoFinal(key, 0);
this.keyOff = 0;
this.ct++;
}

public ECPoint Init_enc(SM2 sm2, ECPoint userKey)
{
AsymmetricCipherKeyPair key = sm2.ecc_key_pair_generator.GenerateKeyPair();
ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters)key.Private;
ECPublicKeyParameters ecpub = (ECPublicKeyParameters)key.Public;
BigInteger k = ecpriv.D;
ECPoint c1 = ecpub.Q;
this.p2 = userKey.Multiply(k);
Reset();
return c1;
}

public void Encrypt(byte[] data)
{
this.sm3c3.BlockUpdate(data, 0, data.Length);
for (int i = 0; i < data.Length; i++)
{
if (keyOff == key.Length)
{
NextKey();
}
data[i] ^= key[keyOff++];
}
}

public void Init_dec(BigInteger userD, ECPoint c1)
{
this.p2 = c1.Multiply(userD);
Reset();
}

public void Decrypt(byte[] data)
{
for (int i = 0; i < data.Length; i++)
{
if (keyOff == key.Length)
{
NextKey();
}
data[i] ^= key[keyOff++];
}

this.sm3c3.BlockUpdate(data, 0, data.Length);
}

public void Dofinal(byte[] c3)
{
byte[] p = byteConvert32Bytes(p2.Normalize().YCoord.ToBigInteger());
this.sm3c3.BlockUpdate(p, 0, p.Length);
this.sm3c3.DoFinal(c3, 0);
Reset();
}
}
private class SM2
{
public static SM2 Instance
{
get
{
return new SM2();
}

}
public static SM2 InstanceTest
{
get
{
return new SM2();
}

}

public static readonly string[] sm2_param = {
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",// p,0
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",// a,1
"28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",// b,2
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",// n,3
"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",// gx,4
"BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0" // gy,5
};

public string[] ecc_param = sm2_param;

public readonly BigInteger ecc_p;
public readonly BigInteger ecc_a;
public readonly BigInteger ecc_b;
public readonly BigInteger ecc_n;
public readonly BigInteger ecc_gx;
public readonly BigInteger ecc_gy;

public readonly ECCurve ecc_curve;
public readonly ECPoint ecc_point_g;

public readonly ECDomainParameters ecc_bc_spec;

public readonly ECKeyPairGenerator ecc_key_pair_generator;

private SM2()
{
ecc_param = sm2_param;

ECFieldElement ecc_gx_fieldelement;
ECFieldElement ecc_gy_fieldelement;

ecc_p = new BigInteger(ecc_param[0], 16);
ecc_a = new BigInteger(ecc_param[1], 16);
ecc_b = new BigInteger(ecc_param[2], 16);
ecc_n = new BigInteger(ecc_param[3], 16);
ecc_gx = new BigInteger(ecc_param[4], 16);
ecc_gy = new BigInteger(ecc_param[5], 16);


ecc_gx_fieldelement = new FpFieldElement(ecc_p, ecc_gx);
ecc_gy_fieldelement = new FpFieldElement(ecc_p, ecc_gy);

ecc_curve = new FpCurve(ecc_p, ecc_a, ecc_b);
ecc_point_g = new FpPoint(ecc_curve, ecc_gx_fieldelement, ecc_gy_fieldelement);

ecc_bc_spec = new ECDomainParameters(ecc_curve, ecc_point_g, ecc_n);

ECKeyGenerationParameters ecc_ecgenparam;
ecc_ecgenparam = new ECKeyGenerationParameters(ecc_bc_spec, new SecureRandom());

ecc_key_pair_generator = new ECKeyPairGenerator();
ecc_key_pair_generator.Init(ecc_ecgenparam);
}

public virtual byte[] Sm2GetZ(byte[] userId, ECPoint userKey)
{
SM3Digest sm3 = new SM3Digest();
byte[] p;
// userId length
int len = userId.Length * 8;
sm3.Update((byte)(len >> 8 & 0x00ff));
sm3.Update((byte)(len & 0x00ff));

// userId
sm3.BlockUpdate(userId, 0, userId.Length);

// a,b
p = ecc_a.ToByteArray();
sm3.BlockUpdate(p, 0, p.Length);
p = ecc_b.ToByteArray();
sm3.BlockUpdate(p, 0, p.Length);
// gx,gy
p = ecc_gx.ToByteArray();
sm3.BlockUpdate(p, 0, p.Length);
p = ecc_gy.ToByteArray();
sm3.BlockUpdate(p, 0, p.Length);

// x,y
p = userKey.AffineXCoord.ToBigInteger().ToByteArray();
sm3.BlockUpdate(p, 0, p.Length);
p = userKey.AffineYCoord.ToBigInteger().ToByteArray();
sm3.BlockUpdate(p, 0, p.Length);

// Z
byte[] md = new byte[sm3.GetDigestSize()];
sm3.DoFinal(md, 0);

return md;
}
}
public class SM2Model
{
/// <summary>
/// 公钥
/// </summary>
public string PublicKey { get; set; }
/// <summary>
/// 私钥
/// </summary>
public string PrivateKey { get; set; }
}
}
}

ZipUtils

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
87
88
89
90
91
92
93
94
95
96
97
98
99
public class ZipUtils
{
public static bool Compress(string compressDirectory, string zipFilePath)
{
ZipOutputStream zipOutputStream = null;
try
{
zipOutputStream = new ZipOutputStream(File.Create(zipFilePath));
zipOutputStream.SetLevel(6);
CompressRec(compressDirectory, zipOutputStream, compressDirectory);
zipOutputStream.Finish();
return true;
}
catch (Exception ex)
{
AppLogger.Err("文件压缩失败!", ex);
return false;
}
finally
{
if (zipOutputStream != null) try { zipOutputStream.Close(); } catch { }
}
}

private static void CompressRec(string currentDirectory, ZipOutputStream zipOutputStream, string rootCompressDirectory)
{
if (currentDirectory[currentDirectory.Length - 1] != Path.DirectorySeparatorChar)
currentDirectory += Path.DirectorySeparatorChar;
Crc32 crc = new Crc32();
string[] curDirFiles = Directory.GetFileSystemEntries(currentDirectory);
foreach (string file in curDirFiles)
{
if (Directory.Exists(file))
CompressRec(file, zipOutputStream, rootCompressDirectory);
else
{
FileStream fs = null;
try
{
fs = File.OpenRead(file);
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
string rootZip = file.Substring(rootCompressDirectory.LastIndexOf(Path.DirectorySeparatorChar) + 1);
ZipEntry entry = new ZipEntry(rootZip)
{
DateTime = DateTime.Now,
Size = fs.Length
};
crc.Reset();
crc.Update(buffer);
entry.Crc = crc.Value;
zipOutputStream.PutNextEntry(entry);
zipOutputStream.Write(buffer, 0, buffer.Length);
}
catch(Exception ex)
{
AppLogger.Err("文件压缩失败!\r\n文件:" + file, ex);
}
finally
{
if (fs != null) try { fs.Close(); } catch { }
}
}
}
}

public static bool Uncompress(string zipFilePath, string extractPath)
{
if (!Directory.Exists(extractPath))
Directory.CreateDirectory(extractPath);
using (ZipArchive archive = System.IO.Compression.ZipFile.OpenRead(zipFilePath))
{
try
{
foreach (ZipArchiveEntry entry in archive.Entries)
{
string entryPath = Path.Combine(extractPath, entry.FullName);
if (entry.FullName.EndsWith("/"))
Directory.CreateDirectory(entryPath);
else
{
string entryFolderPath = Path.GetDirectoryName(entryPath);
if (!Directory.Exists(entryFolderPath))
Directory.CreateDirectory(entryFolderPath);
entry.ExtractToFile(entryPath, overwrite: true);
}
}
return true;
}
catch (Exception ex)
{
AppLogger.Err("ZIP 文件解压失败:" + ex.Message +
"\r\nZipFile:" + zipFilePath +
"\r\nExtract:" + extractPath);
return false;
}
}
}
}

GIS

SheetDesignationUtils

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
public class SheetDesignationUtils
{
private static char[] LatCharArray = {'A','B','C','D','E','F','G','H','I','J','K'
,'L','M','N','O','P','Q','R','S','T','U','V'};
private static char[] ScaleCharArray = { 'A', 'B', 'C', 'R', 'D', 'E', 'F', 'G', 'H' };
private static double[] LatDArray = { 14400, 7200, 3600, 2400, 1200, 600, 300, 150, 75 };
private static double[] LonDArray = { 21600, 10800, 5400, 3600, 1800, 900, 450, 225, 112.5 };

/// <summary>
/// 获取图幅编号
/// </summary>
/// <param name="lon">经度/秒</param>
/// <param name="lat">纬度/秒</param>
/// <param name="scale">比例尺</param>
/// <returns>图幅号</returns>
public static string GetSheetNo(int lon, int lat, SheetScale scale)
{
//*|*|**|*|***|***
if (lat < -(88 * 60 * 60) || lat > 88 * 60 * 60)
throw new Exception("纬度不正确,请检查!");
if (lon < 0 || lon > 180 * 60 * 60)
throw new Exception("经度不正确,请检查!");
string numString = "";
numString += GetMillionRowID(lat);
numString += GetMillionColumnID(lon);
if (scale == SheetScale._1000000)
return numString;
numString += GetScaleID(scale);
numString += GetRowID(lat, scale);
numString += GetColumnID(lon, scale);
return numString;
}

/// <summary>
/// 获取百万比例尺行号
/// </summary>
/// <param name="lat">纬度/秒</param>
/// <returns>百万比例尺行号</returns>
public static char GetMillionRowID(int lat)
{
int a = lat / (4 * 3600);
return LatCharArray[a];
}

/// <summary>
/// 获取百万比例尺列号
/// </summary>
/// <param name="lon">经度/秒</param>
/// <returns>百万比例尺列号</returns>
public static int GetMillionColumnID(int lon)
{
int b = lon / (6 * 3600) + 31;
return b;
}

/// <summary>
/// 获取比例尺代号
/// </summary>
/// <param name="scale">比例尺</param>
/// <returns>比例尺代号</returns>
public static char GetScaleID(SheetScale scale)
{
int scaleIndex = Convert.ToInt32(scale);
char scaleId = ScaleCharArray[scaleIndex];
return scaleId;
}

/// <summary>
/// 获取当前比例尺行号
/// </summary>
/// <param name="lat">纬度/秒</param>
/// <param name="scale">比例尺</param>
/// <returns>当前比例尺行号</returns>
public static string GetRowID(int lat, SheetScale scale)
{
int scaleIndex = Convert.ToInt32(scale);
int c = Convert.ToInt32(4 * 3600 / LatDArray[scaleIndex]) -
Convert.ToInt32(lat % (4 * 3600) / LatDArray[scaleIndex]);
return c.ToString().PadRight(3, '0');
}

/// <summary>
/// 获取当前比例尺列号
/// </summary>
/// <param name="lon">经度/秒</param>
/// <param name="scale">比例尺</param>
/// <returns>当前比例尺列号</returns>
public static string GetColumnID(int lon, SheetScale scale)
{
int scaleIndex = Convert.ToInt32(scale);
int d = Convert.ToInt32(lon % (6 * 3600) / LonDArray[scaleIndex]) + 1;
return d.ToString().PadRight(3, '0');
}

/// <summary>
/// 根据图幅号获取经纬度范围(北半球)
/// </summary>
/// <param name="frmNo">图幅号</param>
/// <returns>图幅范围</returns>
/// <exception cref="Exception">图幅号错误异常</exception>
public static SheetArea GetSheetArea(string frmNo)
{
if (frmNo.Length != 10)
throw new Exception("图幅号错误,请输入标准十位图幅编号!");
int latMillionNum, lonMillionNum, latNum, lonNum, scaleNum;
char latMillionChar, scaleChar;

latMillionChar = char.Parse(frmNo.Substring(0, 1));
latMillionNum = LatCharArray.ToList().IndexOf(latMillionChar);
if (latMillionNum == -1)
throw new Exception("图幅号错误,请检查百万比例尺纬度号!");

scaleChar = char.Parse(frmNo.Substring(3, 1));
scaleNum = ScaleCharArray.ToList().IndexOf(scaleChar);
if (scaleNum == -1)
throw new Exception("图符号错误,请检查比例尺代号!");

if (!int.TryParse(frmNo.Substring(1, 2), out lonMillionNum))
throw new Exception("图幅号错误,请检查百万比例尺经度号!");
if (!int.TryParse(frmNo.Substring(4, 3), out latNum))
throw new Exception("图幅号错误,请检查纬度号!");
if (!int.TryParse(frmNo.Substring(7, 3), out lonNum))
throw new Exception("图幅号错误,请检查经度号!");
SheetArea sheetArea = new SheetArea();
sheetArea.LatMin = latMillionNum * 4 * 3600 + (4 * 3600 / LatDArray[scaleNum] - latNum) * LatDArray[scaleNum];
sheetArea.LatMax = sheetArea.LatMin + LatDArray[scaleNum];

sheetArea.LonMax = (lonMillionNum - 30 - 1) * 6 * 3600 + lonNum * LonDArray[scaleNum];
sheetArea.LonMin = sheetArea.LonMax - LonDArray[scaleNum];
return sheetArea;
}

///// <summary>
///// 根据经度获取6度分带
///// </summary>
///// <param name="centerLongitude"></param>
///// <returns>2000国家大地坐标系6度分带带号</returns>
//public static int GetChinaGeodeticCoordinateSystem2000_6DegreesZone(double centerLongitude)
//{
// centerLongitude = centerLongitude / 3600;
// int ZoneNum = Convert.ToInt32(Math.Round((centerLongitude + 3) / 6, 0));
// return ZoneNum;
//}
}
public class SheetArea
{
public double LonMin { get; set; }
public double LatMin { get; set; }
public double LonMax { get; set; }
public double LatMax { get; set; }
public SheetArea() { }
public SheetArea(double lonMin, double latMin, double lonMax, double latMax)
{
LonMin = lonMin;
LatMin = latMin;
LonMax = lonMax;
LatMax = latMax;
}
}

public enum SheetScale : int
{
_1000000 = 0,
_500000 = 1,
_250000 = 2,
//_200000 = 3,
_100000 = 4,
_50000 = 5,
_25000 = 6,
_10000 = 7,
_5000 = 8
}

ArcGIS Pro

ProAppUtils

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
public class ProAppUtils
{
public static string GetProInstallPath()
{
RegistryKey registryKey = null;
RegistryKey key = null;
try
{
var useRegistryView = Environment.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Registry32;
registryKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, useRegistryView);
key = registryKey.OpenSubKey("SOFTWARE\\ESRI\\ArcGISPro\\Chinese_CN");
if (key == null)
{
Console.WriteLine("未获取到 ArcGIS Pro 安装信息!请检查 ArcGIS Pro 是否正确安装!");
return string.Empty;
}
object proInstallDirObj = key.GetValue("InstallDir");
if (proInstallDirObj == null)
{
Console.WriteLine("未获取到 ArcGIS Pro 安装路径信息!");
return string.Empty;
}
return proInstallDirObj.ToString();
}
catch (Exception ex)
{
Console.WriteLine(ex.GetType().Name + ": " + ex.Message + "\r\n" + ex.StackTrace);
return string.Empty;
}
finally
{
if (registryKey != null)
registryKey.Close();
if (key != null)
key.Close();
}
}

public static void ToggleState(string stateID)
{
if (FrameworkApplication.State.Contains(stateID))
{
FrameworkApplication.State.Deactivate(stateID);
}
else
{
FrameworkApplication.State.Activate(stateID);
}
}

public static void OnApplicationStartup(EventArgs args)
{
//ProMessageUtils.ShowDialog("启动!");
//string testConfig = AppConfig.Static.TestConfig;
//AppConfig.Static.TestConfig = "start";
FrameworkApplication.Current.DispatcherUnhandledException
+= Current_DispatcherUnhandledException;
Assembly assembly = Assembly.LoadFrom(AgpConfig.Path_File_Sqlite_Dll);
Task.Run(() =>
{
TempUtils.Clear();
});
}

private static void Current_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
ProMessageUtils.ShowDialog($"[详情见日志]引发异常:{e.Exception.Message}!", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
AppLogger.Fatal("捕获未处理异常!", e.Exception);
e.Handled = true;
}

public static Task OnApplicationClosing(System.ComponentModel.CancelEventArgs args)
{
args.Cancel = false;
//System.Windows.MessageBoxResult messageBoxResult = ProMessageUtils.ShowDialog("关闭?", "提示", System.Windows.MessageBoxButton.YesNo, System.Windows.MessageBoxImage.Question);
//string testConfig = AppConfig.Static.TestConfig;
//AppConfig.Static.TestConfig = "close";
//if (messageBoxResult != System.Windows.MessageBoxResult.Yes)
// args.Cancel = true;


return Task.FromResult(0);
}

}

ProDialogUtils

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
public class ProDialogUtils
{
public static string OpenFile(string[] FilterItems, string title = "打开文件")
{
OpenItemDialog openItemDialog = new OpenItemDialog()
{
MultiSelect = false,
Title = title,
BrowseFilter= FilterItems.e_ToBrowseProjectFilter()
};
if (!Convert.ToBoolean(openItemDialog.ShowDialog()) || openItemDialog.Items == null || openItemDialog.Items.Count() < 1)
return string.Empty;
return openItemDialog.Items.ElementAt(0).Path;
}

public static string[] OpenFiles(string[] FilterItems, string title = "打开文件")
{
OpenItemDialog openItemDialog = new OpenItemDialog()
{
MultiSelect = true,
Title = title,
BrowseFilter = FilterItems.e_ToBrowseProjectFilter()
};
if (!Convert.ToBoolean(openItemDialog.ShowDialog()) || openItemDialog.Items == null || openItemDialog.Items.Count() < 1)
return new string[] { };
string[] paths = new string[openItemDialog.Items.Count()];
for (int i = 0; i < paths.Length; i++)
paths[i] = openItemDialog.Items.ElementAt(i).Path;
return paths;
}

public static string OpenFolder(string title = "打开文件夹")
{
//OpenItemDialog openItemDialog = new OpenItemDialog()
//{
// MultiSelect = false,
// Title = title,
// Filter = ItemFilters.folders
//};
//if (!Convert.ToBoolean(openItemDialog.ShowDialog()) || openItemDialog.Items == null || openItemDialog.Items.Count() < 1)
// return string.Empty;
//return openItemDialog.Items.ElementAt(0).Path;
return DialogUtils.SelectFolder(title);
}

public static string[] OpenFolders(string title = "打开文件夹")
{
OpenItemDialog openItemDialog = new OpenItemDialog()
{
MultiSelect = true,
Title = title,
Filter = ItemFilters.folders
};
if (!Convert.ToBoolean(openItemDialog.ShowDialog()) || openItemDialog.Items == null || openItemDialog.Items.Count() < 1)
return new string[] { };
string[] paths = new string[openItemDialog.Items.Count()];
for (int i = 0; i < paths.Length; i++)
paths[i] = openItemDialog.Items.ElementAt(i).Path;
return paths;
}

public static string SaveFile(string[] FilterItems, string title = "保存")
{
SaveItemDialog saveItemDialog = new SaveItemDialog()
{
Title = title,
BrowseFilter = FilterItems.e_ToBrowseProjectFilter()
};
if (!Convert.ToBoolean(saveItemDialog.ShowDialog()) || saveItemDialog.FilePath == null)
return string.Empty;
return saveItemDialog.FilePath;
}

public static string SaveFolder(string title = "保存")
{
SaveItemDialog saveItemDialog = new SaveItemDialog()
{
Title = title,
Filter = ItemFilters.folders
};
if (!Convert.ToBoolean(saveItemDialog.ShowDialog()) || saveItemDialog.FilePath == null)
return string.Empty;
string folder = saveItemDialog.FilePath;
if (!string.IsNullOrEmpty(folder) && folder[folder.Length - 1] != Path.DirectorySeparatorChar)
folder += Path.DirectorySeparatorChar;
return folder;
}

//public static SpatialReference SelectSpatialReference(bool showVerticalCoordinateSystems = false)
//{
// SpatialReference spatialReference = null;
// Wnd_SelectSpatialReference wnd_SelectSpatialReference = new Wnd_SelectSpatialReference(showVerticalCoordinateSystems);
// bool? rst = wnd_SelectSpatialReference.ShowDialog();
// if (rst != null && (bool)rst)
// spatialReference = wnd_SelectSpatialReference.SelectSpatialReference;
// return spatialReference;
//}
}


ProFeatureClassUtils

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
public class ProFeatureClassUtils
{
public static string GetGDBFeatureClassIconUrl(GeometryType geometryType)
{
if (geometryType == GeometryType.Point)
return "pack://application:,,,/ArcGIS.Desktop.Resources;component/Images/GeodatabaseFeatureClassPoint32.png";
else if (geometryType == GeometryType.Polyline)
return "pack://application:,,,/ArcGIS.Desktop.Resources;component/Images/GeodatabaseFeatureClassLine32.png";
else if (geometryType == GeometryType.Polygon)
return "pack://application:,,,/ArcGIS.Desktop.Resources;component/Images/GeodatabaseFeatureClassPolygon32.png";
else if (geometryType == GeometryType.Envelope)
return "pack://application:,,,/ArcGIS.Desktop.Resources;component/Images/GeodatabaseFeatureClassDimension32.png";
else if (geometryType == GeometryType.Multipatch)
return "pack://application:,,,/ArcGIS.Desktop.Resources;component/Images/GeodatabaseFeatureClassMultipatch32.png";
else if (geometryType == GeometryType.Multipoint)
return "pack://application:,,,/ArcGIS.Desktop.Resources;component/Images/GeodatabaseFeatureClassMultipoint32.png";
else
return "pack://application:,,,/ArcGIS.Desktop.Resources;component/Images/GeodatabaseFeatureClassUnknown32.png";
}

/// <summary>
/// 获取要素类可编辑字段,必须在QueueTask.Run中执行!
/// </summary>
/// <param name="sourceFeatureClass">要素类</param>
/// <returns>可编辑字段列表</returns>
public static List<Field> GetEditableFields(FeatureClass sourceFeatureClass)
{
List<Field> editableFields = new List<Field>();
IReadOnlyList<Field> targetFields =
sourceFeatureClass
.GetDefinition()
.GetFields()
.ToList();
foreach (var item in targetFields)
if (item.IsEditable)
editableFields.Add(item);
return editableFields;
}
public static void AddFeature(FeatureClass sourceFeatureClass, FeatureClass targetFeatureClass, IList<long> selectionOID)
{
QueuedTask.Run(async () =>
{
List<Field> editableFields = ProFeatureClassUtils.GetEditableFields(targetFeatureClass);
try
{
await ProFeatureClassUtils.CheckExistFields(sourceFeatureClass, editableFields);
}
catch (GeodatabaseFieldException e)
{
ProMessageUtils.ShowDialog(e.Message);
return;
}
bool addField = await AddField(targetFeatureClass, "originalObjectID", FieldType.Integer);
var queryFilter = new QueryFilter();
using(var featureCursor = sourceFeatureClass.Search(queryFilter))
{
while (featureCursor.MoveNext())
{
var feature = featureCursor.Current as Feature;
long curOID = feature.GetObjectID();
if (!selectionOID.Contains(curOID))
continue;
using (RowBuffer rowBuffer = targetFeatureClass.CreateRowBuffer())
{
Feature newFeature = targetFeatureClass.CreateRow(rowBuffer);
newFeature.SetShape(feature.GetShape());
foreach (var field in newFeature.GetFields())
if (field.IsEditable && field.Name != "originalObjectID")
newFeature[field.Name] = feature[field.Name];
newFeature["originalObjectID"] = curOID;
newFeature.Store();
}
}
}
});
}
public static async Task<bool> AddField(FeatureClass featureClass, string fieldName, FieldType fieldType)
{
bool rst = await QueuedTask.Run(() =>
{
FeatureClassDefinition originalFeatureClassDefinition = featureClass.GetDefinition();
FeatureClassDescription originalFeatureClassDescription =
new FeatureClassDescription(originalFeatureClassDefinition);
FieldDescription newFieldDescription =
new FieldDescription(fieldName, fieldType);
List<FieldDescription> modifiedFieldDescriptions =
new List<FieldDescription>(originalFeatureClassDescription.FieldDescriptions)
{
newFieldDescription
};
FeatureClassDescription modifiedFeatureClassDescription =
new FeatureClassDescription(originalFeatureClassDescription.Name,
modifiedFieldDescriptions, originalFeatureClassDescription.ShapeDescription);
Geodatabase geodatabase = featureClass.GetDatastore() as Geodatabase;
SchemaBuilder schemaBuilder = new SchemaBuilder(geodatabase);
schemaBuilder.Modify(modifiedFeatureClassDescription);
bool modifyStatus = schemaBuilder.Build();
if (!modifyStatus)
{
//IReadOnlyList<string> errors = schemaBuilder.ErrorMessages;
//foreach (var item in errors)
// msg_ += item.ToString() + "\r\n";
return false;
}
return true;
});
return rst;
}
public static async Task<bool> AddField(FeatureClass featureClass, string fieldName, string aliasName, FieldType fieldType)
{
bool rst = await QueuedTask.Run(() =>
{
FeatureClassDefinition originalFeatureClassDefinition = featureClass.GetDefinition();
FeatureClassDescription originalFeatureClassDescription =
new FeatureClassDescription(originalFeatureClassDefinition);
FieldDescription newFieldDescription =
new FieldDescription(fieldName, fieldType) {AliasName = aliasName };
List<FieldDescription> modifiedFieldDescriptions =
new List<FieldDescription>(originalFeatureClassDescription.FieldDescriptions)
{
newFieldDescription
};
FeatureClassDescription modifiedFeatureClassDescription =
new FeatureClassDescription(originalFeatureClassDescription.Name,
modifiedFieldDescriptions, originalFeatureClassDescription.ShapeDescription);
Geodatabase geodatabase = featureClass.GetDatastore() as Geodatabase;
SchemaBuilder schemaBuilder = new SchemaBuilder(geodatabase);
schemaBuilder.Modify(modifiedFeatureClassDescription);
bool modifyStatus = schemaBuilder.Build();
if (!modifyStatus)
{
//IReadOnlyList<string> errors = schemaBuilder.ErrorMessages;
//foreach (var item in errors)
// msg_ += item.ToString() + "\r\n";
return false;
}
return true;
});
return rst;
}
public static async Task CheckExistFields(FeatureClass targetFeatureClass, IEnumerable<Field> fields)
{
await QueuedTask.Run(() =>
{
IReadOnlyList<Field> targetFields = targetFeatureClass.GetDefinition().GetFields();
foreach (Field field in fields)
{
bool fieldExist = false;
foreach (Field targetField in targetFields)
{
if (field.Name.Equals(targetField.Name, StringComparison.OrdinalIgnoreCase) &&
field.FieldType == targetField.FieldType)
{
fieldExist = true;
break;
}
}
if (!fieldExist)
throw new GeodatabaseFieldException(
$"未找到字段:{{Name: {field.Name}, FieldType: {field.FieldType}}}");
}
});
}
public static void AddFeature(FeatureClass sourceFeatureClass, FeatureClass targetFeatureClass)
{
var ps = new ProgressorSource("添加要素...");
QueuedTask.Run(async () =>
{
List<Field> editableFields = ProFeatureClassUtils.GetEditableFields(targetFeatureClass);
try
{
await ProFeatureClassUtils.CheckExistFields(sourceFeatureClass, editableFields);
}
catch (GeodatabaseFieldException e)
{
ProMessageUtils.ShowDialog(e.Message);
return;
}
using (RowCursor featureCursor = sourceFeatureClass.Search())
{
while (featureCursor.MoveNext())
{
Feature feature = featureCursor.Current as Feature;
long curOID = feature.GetObjectID();
using (RowBuffer rowBuffer = targetFeatureClass.CreateRowBuffer())
{
Feature newFeature = targetFeatureClass.CreateRow(rowBuffer);
newFeature.SetShape(feature.GetShape());
foreach (var field in newFeature.GetFields())
if (field.IsEditable)
newFeature[field.Name] = feature[field.Name];
newFeature.Store();
}
}
}
}, ps.Progressor);
}

/// <summary>
/// 更新/插入要素,必须在QueueTask.Run中执行!
/// </summary>
/// <param name="sourceFeatureClass">源要素类</param>
/// <param name="targetFeatureClass">目标要素类</param>
/// <param name="keyFields">主键字段</param>
/// <returns>结果</returns>
public static bool UpdateOrInsert(FeatureClass sourceFeatureClass, FeatureClass targetFeatureClass, string[] keyFields)
{
if (keyFields != null)
{
foreach (string keyField in keyFields)
{
int targetKeyFieldIdx = targetFeatureClass.GetDefinition().FindField(keyField);
if (targetKeyFieldIdx < 0)
{
ProMessageUtils.ShowDialog(
$"目标要素类不包含主键字段:{keyField}!",
"错误", System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Error);
return false;
}
int sourceKeyFieldIdx = sourceFeatureClass.GetDefinition().FindField(keyField);
if (sourceKeyFieldIdx < 0)
{
ProMessageUtils.ShowDialog(
$"源要素类不包含主键字段:{keyField}!",
"错误", System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Error);
return false;
}
}
}

using (RowCursor sourceFeatureCursor = sourceFeatureClass.Search())
{
while (sourceFeatureCursor.MoveNext())
{
Feature sourceFeature = sourceFeatureCursor.Current as Feature;
if (sourceFeature == null)
continue;
bool isExistsFeature = false;
if (keyFields != null)
{
QueryFilter filter = new QueryFilter();
for (int i = 0; i < keyFields.Length; i++)
{
object keyFieldValue = sourceFeature[keyFields[i]];
filter.WhereClause += (i == 0 ? "" : " AND ") + $"{keyFields[i]}='{keyFieldValue}'";
}
using (RowCursor targetFeatureCursor = targetFeatureClass.Search(filter))
{
while (targetFeatureCursor.MoveNext())
{
Feature targetFeature = targetFeatureCursor.Current as Feature;
if (targetFeature == null)
continue;
targetFeature.SetShape(sourceFeature.GetShape());
foreach (var field in targetFeature.GetFields())
{
if (field.IsEditable)
{
try
{
targetFeature[field.Name] = sourceFeature[field.Name];
}
catch (Exception ex)
{
}
}
}
targetFeature.Store();
isExistsFeature = true;
}
}
}

if (isExistsFeature)
continue;
using (RowBuffer rowBuffer = targetFeatureClass.CreateRowBuffer())
{
try
{
Feature newFeature = targetFeatureClass.CreateRow(rowBuffer);
newFeature.SetShape(sourceFeature.GetShape());
foreach (var field in newFeature.GetFields())
{
if (field.IsEditable)
{
try
{
newFeature[field.Name] = sourceFeature[field.Name];
}
catch { }
}
}
newFeature.Store();
}
catch (GeodatabaseObjectClassException ex)
{
if(ex.Message == "Objects in this object class cannot be updated outside of an edit session.")
AppLogger.Err("");
throw new Exception(ex.Message);
}
}
}
}
return true;
}
/// <summary>
/// 更新/插入要素,必须在QueueTask.Run中执行!
/// </summary>
/// <param name="sourceFeatureClass">源要素类</param>
/// <param name="targetFeatureClass">目标要素类</param>
/// <param name="keyFields">主键字段</param>
/// <param name="ps">进度器</param>
/// <returns>结果</returns>
public static bool UpdateOrInsert(FeatureClass sourceFeatureClass, FeatureClass targetFeatureClass, string[] keyFields, ProgressorSource ps)
{
if (keyFields != null)
{
foreach (string keyField in keyFields)
{
int targetKeyFieldIdx = targetFeatureClass.GetDefinition().FindField(keyField);
if (targetKeyFieldIdx < 0)
{
ProMessageUtils.ShowDialog(
$"目标要素类不包含主键字段:{keyField}!",
"错误", System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Error);
return false;
}
int sourceKeyFieldIdx = sourceFeatureClass.GetDefinition().FindField(keyField);
if (sourceKeyFieldIdx < 0)
{
ProMessageUtils.ShowDialog(
$"源要素类不包含主键字段:{keyField}!",
"错误", System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Error);
return false;
}
}
}
long num = 0;
long count = sourceFeatureClass.GetCount();
using (RowCursor sourceFeatureCursor = sourceFeatureClass.Search())
{
while (sourceFeatureCursor.MoveNext())
{
if (ps != null)
ps.Progressor.Message = $"执行中...({++num}/{count})";
Feature sourceFeature = sourceFeatureCursor.Current as Feature;
if (sourceFeature == null)
continue;
bool isExistsFeature = false;
if (keyFields != null)
{
QueryFilter filter = new QueryFilter();
for (int i = 0; i < keyFields.Length; i++)
{
object keyFieldValue = sourceFeature[keyFields[i]];
filter.WhereClause += (i == 0 ? "" : " AND ") + $"{keyFields[i]}='{keyFieldValue}'";
}
using (RowCursor targetFeatureCursor = targetFeatureClass.Search(filter))
{
while (targetFeatureCursor.MoveNext())
{
Feature targetFeature = targetFeatureCursor.Current as Feature;
if (targetFeature == null)
continue;
targetFeature.SetShape(sourceFeature.GetShape());
foreach (var field in targetFeature.GetFields())
{
if (field.IsEditable)
{
try
{
targetFeature[field.Name] = sourceFeature[field.Name];
}
catch (Exception ex)
{
}
}
}
targetFeature.Store();
isExistsFeature = true;
}
}
}
if (isExistsFeature)
continue;
using (RowBuffer rowBuffer = targetFeatureClass.CreateRowBuffer())
{
Feature newFeature = targetFeatureClass.CreateRow(rowBuffer);
newFeature.SetShape(sourceFeature.GetShape());
foreach (var field in newFeature.GetFields())
{
if (field.IsEditable)
{
try
{
newFeature[field.Name] = sourceFeature[field.Name];
}
catch (Exception ex)
{
}
}
}
newFeature.Store();
}
}
}
return true;
}
/// <summary>
/// 更新/插入要素,必须在QueueTask.Run中执行!
/// </summary>
/// <param name="sourceFeatureClass">源要素类</param>
/// <param name="targetFeatureClass">目标要素类</param>
/// <param name="keyFields">主键字段</param>
/// <param name="exceptionOperate">异常操作</param>
/// <param name="progressOperate">进度操作</param>
/// <returns>结果</returns>
public static bool UpdateOrInsert(FeatureClass sourceFeatureClass, FeatureClass targetFeatureClass,
string[] keyFields, Action<string, Exception> exceptionOperate,
Func<long, long, bool> progressOperate)
{
if (keyFields != null)
{
foreach (string keyField in keyFields)
{
int targetKeyFieldIdx = targetFeatureClass.GetDefinition().FindField(keyField);
if (targetKeyFieldIdx < 0)
{
if (exceptionOperate != null)
exceptionOperate($"目标要素类不包含主键字段:{keyField}!", null);
return false;
}
int sourceKeyFieldIdx = sourceFeatureClass.GetDefinition().FindField(keyField);
if (sourceKeyFieldIdx < 0)
{
exceptionOperate($"源要素类不包含主键字段:{keyField}!", null);
return false;
}
}
}
long num = 0;
long count = sourceFeatureClass.GetCount();
using (RowCursor sourceFeatureCursor = sourceFeatureClass.Search())
{
while (sourceFeatureCursor.MoveNext())
{
if (progressOperate != null)
{
bool stopSign = progressOperate(++num, count);
if (stopSign)
break;
}
Feature sourceFeature = sourceFeatureCursor.Current as Feature;
if (sourceFeature == null)
continue;
bool isExistsFeature = false;
if (keyFields != null)
{
QueryFilter filter = new QueryFilter();
for (int i = 0; i < keyFields.Length; i++)
{
object keyFieldValue = sourceFeature[keyFields[i]];
filter.WhereClause += (i == 0 ? "" : " AND ") + $"{keyFields[i]}='{keyFieldValue}'";
}
using (RowCursor targetFeatureCursor = targetFeatureClass.Search(filter))
{
while (targetFeatureCursor.MoveNext())
{
Feature targetFeature = targetFeatureCursor.Current as Feature;
if (targetFeature == null)
continue;
targetFeature.SetShape(sourceFeature.GetShape());
foreach (var field in targetFeature.GetFields())
{
if (field.IsEditable)
{
try
{
object val = sourceFeature[field.Name];
targetFeature[field.Name] = val;
}
catch (Exception ex)
{
}
}
}
targetFeature.Store();
isExistsFeature = true;
}
}
}
if (isExistsFeature)
continue;
using (RowBuffer rowBuffer = targetFeatureClass.CreateRowBuffer())
{
Feature newFeature = targetFeatureClass.CreateRow(rowBuffer);
newFeature.SetShape(sourceFeature.GetShape());
foreach (var field in newFeature.GetFields())
{
if (field.IsEditable)
{
try
{
newFeature[field.Name] = sourceFeature[field.Name];
}
catch (Exception ex)
{
}
}
}
newFeature.Store();
}
}
}
return true;
}

public static FeatureClass Open(string url)
{
Item item = ItemFactory.Instance.Create(url);
if (item.PhysicalPath.EndsWith(".gdb", StringComparison.OrdinalIgnoreCase))
{
using (Geodatabase gdb = new Geodatabase(
new FileGeodatabaseConnectionPath(new Uri(item.PhysicalPath))))
{
try
{
FeatureClass fc = gdb.OpenDataset<FeatureClass>(item.Name);
return fc;
}
catch (Exception ex)
{
string msg = $"要素类未能正确打开:\r\n{url}";
AppLogger.Err(msg, ex);
return null;
}
}
}
else if (item.Path.EndsWith(".shp", StringComparison.OrdinalIgnoreCase))
{
FeatureClass fc = ProShpUtils.OpenShapefileFeatureClass(item.Path);
return fc;
}
else
{
string msg = $"未知要素类类型:\r\n{url}";
AppLogger.Err(msg);
return null;
}
}

public static IGPResult FeatureClassToFeatureClass(string inFeatureClass, string outGdb, string outName = null)
{
if (string.IsNullOrEmpty(outName))
outName = Path.GetFileNameWithoutExtension(inFeatureClass);
object[] pars = new object[] { inFeatureClass, outGdb, outName };
IGPResult result = null;
Task task = Task.Run(async () =>
{
result = await ProGpUtils.RunGP("conversion.FeatureClassToFeatureClass", pars);
});
task.Wait();
return result;
}
}

ProFeatureLayerUtils

1
2
3
4
5
6
7
8
9
10
public class ProFeatureLayerUtils
{
public static async Task<FeatureClass> GetFeatureClass(FeatureLayer featureLayer)
{
return await QueuedTask.Run(() =>
{
return featureLayer.GetFeatureClass();
});
}
}

ProGdbUtils

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
public class ProGdbUtils
{
public static bool DeleteFeatureClass(Geodatabase geodatabase, string className)
{
try
{
FeatureClass featureClass = geodatabase.OpenDataset<FeatureClass>(className);
FeatureClassDescription featureClassDescription =
new FeatureClassDescription(featureClass.GetDefinition());
SchemaBuilder schemaBuilder = new SchemaBuilder(geodatabase);
schemaBuilder.Delete(featureClassDescription);
bool success = schemaBuilder.Build();
return success;
}
catch (Exception ex)
{
AppLogger.Err("删除要素类失败:" + ex.Message, ex);
return false;
}
}

public static bool ClearFeatureClass(Geodatabase geodatabase, string className)
{
try
{
FeatureClass featureClass = geodatabase.OpenDataset<FeatureClass>(className);
EditOperation editOperation = new EditOperation();
editOperation.Callback(context =>
{
using (RowCursor rowCursor = featureClass.Search(useRecyclingCursor:false))
{
while (rowCursor.MoveNext())
{
using (Row row = rowCursor.Current)
{
context.Invalidate(row);
row.Delete();
}
}
}
}, featureClass);
try
{
bool rst = editOperation.Execute();
if (!rst)
AppLogger.Err("要素类清空失败:" + editOperation.ErrorMessage);
return rst;
}
catch (GeodatabaseException geoEx)
{
AppLogger.Err("要素类清空失败!", geoEx);
return false;
}
}
catch (Exception ex)
{
AppLogger.Err("清空要素类失败:" + ex.Message, ex);
return false;
}
}

public static async Task<Geodatabase> CreateGDBMCT(string gdbPath)
{
var ps = new ProgressorSource("正在创建文件地理数据库...");
return await QueuedTask.Run(() =>
{
string folderPath = System.IO.Path.GetDirectoryName(gdbPath);
if (!Directory.Exists(folderPath))
Directory.CreateDirectory(folderPath);
FileGeodatabaseConnectionPath fileGeodatabaseConnectionPath = new FileGeodatabaseConnectionPath(new Uri(gdbPath));
Geodatabase geodatabase = SchemaBuilder.CreateGeodatabase(fileGeodatabaseConnectionPath);
return geodatabase;
}, ps.Progressor);
}

public static async Task<Geodatabase> OpenOrCreateGDBMCT(string gdbPath)
{
var ps = new ProgressorSource("正在创建文件地理数据库...");
return await QueuedTask.Run(() =>
{
Geodatabase geodatabase = null;
try
{
geodatabase = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(gdbPath)));
}
catch
{
string folderPath = System.IO.Path.GetDirectoryName(gdbPath);
if (!Directory.Exists(folderPath))
Directory.CreateDirectory(folderPath);
FileGeodatabaseConnectionPath fileGeodatabaseConnectionPath = new FileGeodatabaseConnectionPath(new Uri(gdbPath));
geodatabase = SchemaBuilder.CreateGeodatabase(fileGeodatabaseConnectionPath);
}
return geodatabase;
}, ps.Progressor);
}

/// <summary>
/// 创建文件地理数据库,必须在QueueTask.Run中执行!
/// </summary>
/// <param name="gdbPath">gdb路径</param>
/// <param name="ps">进度器</param>
/// <returns>新GDB</returns>
public static Geodatabase CreateGDB(string gdbPath, ProgressorSource ps = null)
{
if (ps != null)
ps.Progressor.Message = "正在创建文件地理数据库...";
string folderPath = System.IO.Path.GetDirectoryName(gdbPath);
if (!Directory.Exists(folderPath))
Directory.CreateDirectory(folderPath);
FileGeodatabaseConnectionPath fileGeodatabaseConnectionPath = new FileGeodatabaseConnectionPath(new Uri(gdbPath));
Geodatabase geodatabase = SchemaBuilder.CreateGeodatabase(fileGeodatabaseConnectionPath);
return geodatabase;
}

public static FeatureClass CreateFeatureClass(
Geodatabase geodatabase, FeatureClass featureClass,
string featureClassName = null, string featureClassAliasName = null)
{
FeatureClass newFeatureClass = null;
var ps = new ProgressorSource("正在创建要素类...");
FeatureClassDescription featureClassDescription = null;
if (featureClassName != null)
{
FeatureClassDefinition _featureClassDefinition_ = featureClass.GetDefinition();
FeatureClassDescription _featureClassDescription_ = new FeatureClassDescription(_featureClassDefinition_);
featureClassDescription = new FeatureClassDescription(featureClassName, _featureClassDescription_.FieldDescriptions, _featureClassDescription_.ShapeDescription);
if (featureClassAliasName != null)
featureClassDescription.AliasName = featureClassAliasName;
}
else
{
FeatureClassDefinition featureClassDefinition = featureClass.GetDefinition();
featureClassDescription = new FeatureClassDescription(featureClassDefinition);
if (featureClassAliasName != null)
featureClassDescription.AliasName = featureClassAliasName;
}
SchemaBuilder schemaBuilder = new SchemaBuilder(geodatabase);
schemaBuilder.Create(featureClassDescription);
bool createClass = schemaBuilder.Build();
if (!createClass)
{
return null;
}
if (featureClassName == null)
newFeatureClass = geodatabase.OpenDataset<FeatureClass>(featureClassDescription.Name);
else
newFeatureClass = geodatabase.OpenDataset<FeatureClass>(featureClassName);
return newFeatureClass;
}

public static async Task<FeatureClass> CreateFeatureClass(
Geodatabase geodatabase,
string featureClassName,
ShapeDescription shapeDescription,
IEnumerable<FieldDescription> fieldDescriptions)
{
FeatureClass newFeatureClass = null;
var ps = new ProgressorSource("正在创建要素类...");
await QueuedTask.Run(() =>
{
FeatureClassDescription featureClassDescription =
new FeatureClassDescription(
featureClassName,
(IReadOnlyList<FieldDescription>)fieldDescriptions,
shapeDescription);
SchemaBuilder schemaBuilder = new SchemaBuilder(geodatabase);
schemaBuilder.Create(featureClassDescription);
bool success = schemaBuilder.Build();
if (success)
{
newFeatureClass = geodatabase.OpenDataset<FeatureClass>(featureClassName);
}
else
{
//string error = schemaBuilder.ErrorMessages.ToArray().e_Connect("\r\n");
//LogUtils.AppLog("创建要素类失败!\r\n" + error, Enum.LogLevel.Error);
}
},ps.Progressor);
return newFeatureClass;
}

/// <summary>
/// 检查要素类是否已创建,必须在QueueTask.Run中执行!
/// </summary>
/// <param name="geodatabase">地理数据库</param>
/// <param name="featureClassName">要素类名</param>
/// <returns>结果</returns>
public static bool FeatureClassExists(Geodatabase geodatabase, string featureClassName, ProgressorSource ps = null)
{
bool featureClassExists = false;
if (ps != null)
ps.Progressor.Message = "检查表是否已创建...";
try
{
IReadOnlyList<FeatureClassDefinition> featureClassDefinitions = geodatabase.GetDefinitions<FeatureClassDefinition>();
FeatureClassDefinition featureClassDefinition = geodatabase.GetDefinition<FeatureClassDefinition>(featureClassName);
featureClassDefinition.Dispose();
featureClassExists = true;
}
catch
{
// GetDefinition throws an exception if the definition doesn't exist
}
return featureClassExists;
}

/// <summary>
/// 检查表是否已创建,必须在QueueTask.Run中执行!
/// </summary>
/// <param name="geodatabase">地理数据库</param>
/// <param name="tableName">表名</param>
/// <param name="ps">进度器</param>
/// <returns>表是否已创建</returns>
public static bool TableExists(Geodatabase geodatabase, string tableName, ProgressorSource ps = null)
{
bool tableExists = false;
if (ps != null)
ps.Progressor.Message = "检查表是否已创建...";
try
{
IReadOnlyList<TableDefinition> tableDefinitions = geodatabase.GetDefinitions<TableDefinition>();
TableDefinition tableDefinition = geodatabase.GetDefinition<TableDefinition>(tableName);
tableDefinition.Dispose();
tableExists = true;
}
catch
{
// GetDefinition throws an exception if the definition doesn't exist
}
return tableExists;
}

/// <summary>
/// 创建表,必须在QueueTask.Run中执行!
/// </summary>
/// <param name="geodatabase">地理数据库</param>
/// <param name="tableName">表名</param>
/// <param name="dataTable">数据表结构</param>
/// <param name="ps">进度器</param>
/// <returns>新表</returns>
public static Table CreateTable(Geodatabase geodatabase, string tableName, DataTable dataTable, ProgressorSource ps = null)
{
Table table = null;
try
{
if (ps != null)
ps.Progressor.Message = "创建表...";
FieldDescription globalIDFieldDescription = FieldDescription.CreateGlobalIDField();
FieldDescription objectIDFieldDescription = FieldDescription.CreateObjectIDField();
List<FieldDescription> fieldDescriptions = new List<FieldDescription>()
{
globalIDFieldDescription, objectIDFieldDescription
};
for (int i = 0; i < dataTable.Columns.Count; i++)
{
FieldDescription fieldDescription1 = fieldDescriptions.Find(f => f.Name.ToLower() == dataTable.Columns[i].ColumnName.ToLower());
if (fieldDescription1 != null) continue;
FieldDescription fieldDescription = FieldDescription.CreateStringField(dataTable.Columns[i].ColumnName, 512);
fieldDescriptions.Add(fieldDescription);
}
TableDescription tableDescription = new TableDescription(tableName, fieldDescriptions);
SchemaBuilder schemaBuilder = new SchemaBuilder(geodatabase);
schemaBuilder.Create(tableDescription);
bool success = schemaBuilder.Build();
if (!success)
{
//IReadOnlyList<string> errorMessages = schemaBuilder.ErrorMessages;
//foreach (var item in errorMessages)
// LogUtils.AppLog("表创建失败!\r\n" + item, Enum.LogLevel.Error);
}
else
table = geodatabase.OpenDataset<Table>(tableName);
}
catch (Exception ex)
{
ProMessageUtils.ShowDialog(ex.Message);
}
return table;
}

public static Table CreateTable(Geodatabase geodatabase, string tableName, List<FieldDescription> fieldDescriptions, ProgressorSource ps = null)
{
Table table = null;
try
{
if (ps != null)
ps.Progressor.Message = "创建表...";
if (fieldDescriptions == null)
fieldDescriptions = new List<FieldDescription>();
List<FieldDescription> fieldDescriptionsCreate = new List<FieldDescription>();
FieldDescription objectIDFieldDescription = FieldDescription.CreateObjectIDField();
FieldDescription globalIDFieldDescription = FieldDescription.CreateGlobalIDField();
fieldDescriptionsCreate.Add(globalIDFieldDescription);
fieldDescriptionsCreate.Add(objectIDFieldDescription);

TableDescription tableDescription = new TableDescription(tableName, fieldDescriptionsCreate);
SchemaBuilder schemaBuilder = new SchemaBuilder(geodatabase);
schemaBuilder.Create(tableDescription);
bool success = schemaBuilder.Build();
if (!success)
{
//IReadOnlyList<string> errorMessages = schemaBuilder.ErrorMessages;
//foreach (var item in errorMessages)
// LogUtils.AppLog("表创建失败!\r\n" + item, Enum.LogLevel.Error);
return null;
}

table = geodatabase.OpenDataset<Table>(tableName);

IReadOnlyList<ArcGIS.Core.Data.Field> fields = table.GetDefinition().GetFields();
TableDescription tableDescriptionModify = new TableDescription(table.GetDefinition());
List<FieldDescription> fieldDescriptionsModify = new List<FieldDescription>(tableDescriptionModify.FieldDescriptions);
foreach (var field in fieldDescriptions)
if (fields.FirstOrDefault(f => f.Name.ToLower() == field.Name.ToLower()) == null)
fieldDescriptionsModify.Add(field);
tableDescription = new TableDescription(tableName, fieldDescriptionsModify);
schemaBuilder.Modify(tableDescription);
success = schemaBuilder.Build();
if (!success)
{
//IReadOnlyList<string> errorMessages = schemaBuilder.ErrorMessages;
//foreach (var item in errorMessages)
// LogUtils.AppLog("添加表字段失败!\r\n" + item, Enum.LogLevel.Error);
return null;
}
table = geodatabase.OpenDataset<Table>(tableName);
}
catch (Exception ex)
{
ProMessageUtils.ShowDialog(ex.Message);
}
return table;
}
/// <summary>
/// 创建表,必须在QueueTask.Run中执行!
/// </summary>
/// <param name="geodatabase">地理数据库</param>
/// <param name="tableName">表名</param>
/// <param name="dataTable">数据表结构</param>
/// <param name="ps">进度器</param>
/// <returns>新表</returns>
public static Table CreateTable(Geodatabase geodatabase, string tableName, Table table, ProgressorSource ps = null)
{
Table newTable = null;
try
{
if (ps != null)
ps.Progressor.Message = "创建表...";
FieldDescription globalIDFieldDescription = FieldDescription.CreateGlobalIDField();
FieldDescription objectIDFieldDescription = FieldDescription.CreateObjectIDField();
List<FieldDescription> fieldDescriptions = new List<FieldDescription>()
{
globalIDFieldDescription, objectIDFieldDescription
};
foreach (var field in table.GetDefinition().GetFields())
{
FieldDescription fieldDescription1 = fieldDescriptions.Find(f => f.Name.ToLower() == field.Name.ToLower());
if (fieldDescription1 != null) continue;
FieldDescription fieldDescription = new FieldDescription(field);
fieldDescriptions.Add(fieldDescription);
}
TableDescription tableDescription = new TableDescription(tableName, fieldDescriptions);
SchemaBuilder schemaBuilder = new SchemaBuilder(geodatabase);
schemaBuilder.Create(tableDescription);
bool success = schemaBuilder.Build();
if (!success)
{
//IReadOnlyList<string> errorMessages = schemaBuilder.ErrorMessages;
//foreach (var item in errorMessages)
// LogUtils.AppLog("表创建失败!\r\n" + item, Enum.LogLevel.Error);
return null;
}
newTable = geodatabase.OpenDataset<Table>(tableName);
}
catch (Exception ex)
{
ProMessageUtils.ShowDialog(ex.Message);
}
return newTable;
}

public static Geodatabase OpenEnterpriseGeodatabase(
string instance,
string database,
string user,
string password,
EnterpriseDatabaseType enterpriseDatabaseType = EnterpriseDatabaseType.PostgreSQL)
{
Geodatabase geodatabase = null;
try
{
DatabaseConnectionProperties connectionProperties =
new DatabaseConnectionProperties(enterpriseDatabaseType)
{
AuthenticationMode = AuthenticationMode.DBMS,
Instance = instance,
Database = database,
User = user,
Password = password
};
geodatabase = new Geodatabase(connectionProperties);
}
catch (Exception ex)
{
AppLogger.Err(ex.Message, ex);
//LogUtils.AppLog("连接SDE数据库失败!", Enum.LogLevel.Warning, ex);
}
return geodatabase;
}

public static Geodatabase OpenEnterpriseGeodatabase(
string instance,
string database,
string user,
string password,
bool clearLocks,
EnterpriseDatabaseType enterpriseDatabaseType = EnterpriseDatabaseType.PostgreSQL)
{
Geodatabase geodatabase = null;
try
{
DatabaseConnectionProperties connectionProperties =
new DatabaseConnectionProperties(enterpriseDatabaseType)
{
AuthenticationMode = AuthenticationMode.DBMS,
Instance = instance,
Database = database,
User = user,
Password = password
};
geodatabase = new Geodatabase(connectionProperties);
if (clearLocks)
{
//sde_table_locks
}
}
catch (Exception ex)
{
AppLogger.Err(ex.Message, ex);
//LogUtils.AppLog("连接SDE数据库失败!", Enum.LogLevel.Warning, ex);
}
return geodatabase;
}

public static Geodatabase OpenEnterpriseGeodatabaseMCT(
string instance,
string database,
string user,
string password,
EnterpriseDatabaseType enterpriseDatabaseType = EnterpriseDatabaseType.PostgreSQL)
{
Geodatabase geodatabase = null;
Task task = Task.Run(async() =>
{
var ps = new ProgressorSource("连接企业级SDE数据库...");
await QueuedTask.Run(() =>
{
try
{
DatabaseConnectionProperties connectionProperties =
new DatabaseConnectionProperties(enterpriseDatabaseType)
{
AuthenticationMode = AuthenticationMode.DBMS,
Instance = instance,
Database = database,
User = user,
Password = password
};
geodatabase = new Geodatabase(connectionProperties);
}
catch (Exception ex)
{
//LogUtils.AppLog("连接SDE数据库失败!", Enum.LogLevel.Warning, ex);
}
}, ps.Progressor);
});
task.Wait();
return geodatabase;
}

public static FeatureDataset CreateFeatureDataset(Geodatabase geodatabase, string name, SpatialReference sr = null)
{
if (sr == null)
sr = SpatialReferences.WGS84;
SchemaBuilder schemaBuilder = new SchemaBuilder(geodatabase);
FeatureDatasetDescription featureDatasetDescription =
new FeatureDatasetDescription(name, sr);
schemaBuilder.Create(featureDatasetDescription);
bool buildStatus = schemaBuilder.Build();
if (!buildStatus)
{
string errors = schemaBuilder.ErrorMessages.ToList().e_Connect("\r\n");
AppLogger.Err("创建要素数据集失败!\r\n" + errors);
return null;
}
FeatureDataset featureDataset = geodatabase.OpenDataset<FeatureDataset>(name);
return featureDataset;
}
}

ProGpUtils

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
public class ProGpUtils
{
public static async Task<IGPResult> RunGP(
string tool_path, object[] pars,
Action<string> processMessage,
Action<int> processProgress)
{
GPExecuteToolFlags toolFlags = GPExecuteToolFlags.None;
IGPResult result = null;
UiUtils.Invoke(async() =>
{
var args = Geoprocessing.MakeValueArray(pars);
System.Threading.CancellationTokenSource _cts = new System.Threading.CancellationTokenSource();
result = await Geoprocessing.ExecuteToolAsync(tool_path, args, null, _cts.Token,
(event_name, obj) =>
{
switch (event_name)
{
case "OnValidate":
IGPMessage[] onValidate = obj as IGPMessage[];
if (onValidate != null)
{
foreach (var item in onValidate)
{
processMessage(item.Text);
}
}
if (onValidate != null && onValidate.Any(it => it.Type == GPMessageType.Warning))
_cts.Cancel();
break;
case "OnProgressMessage":
processMessage((string)obj);
break;
case "OnProgressPos":
if ((int)obj == -1 || (int)obj == 0)
break;
processProgress((int)obj);
break;
case "OnMessage":
IGPMessage onMessage = obj as IGPMessage;
if (onMessage != null)
processMessage(onMessage.Text);
break;
}
}, toolFlags);
_cts.Dispose();
});
return result;
}
public static async Task<IGPResult> RunGP(
string tool_path, object[] pars)
{
IGPResult result = null;
GPExecuteToolFlags toolFlags = GPExecuteToolFlags.None;
var args = Geoprocessing.MakeValueArray(pars);
result = await Geoprocessing.ExecuteToolAsync(tool_path, args, null, null, null, toolFlags);
return result;
}

public static string GetGPResultErr(IGPResult result)
{
string msg = string.Empty;
foreach (var item in result.Messages)
msg += $"错误代码:{item.ErrorCode} 错误信息:{item.Text}\r\n";
return msg;
}
}

ProMessageUtils

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
87
88
89
public class ProMessageUtils
{
public static MessageBoxResult ShowDialog(string message, string title = "提示", MessageBoxButton messageBoxButton = MessageBoxButton.OK, MessageBoxImage messageBoxImage = MessageBoxImage.Information, MessageBoxResult messageBoxResult = MessageBoxResult.None)
{
return ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(message, title, messageBoxButton, messageBoxImage, messageBoxResult);
}
public static MessageBoxResult ShowDialogInfo(string message, string title = "提示")
{
return ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(message, title, MessageBoxButton.OK, MessageBoxImage.Information);
}
public static MessageBoxResult ShowDialogWarn(string message, string title = "异常")
{
return ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(message, title, MessageBoxButton.OK, MessageBoxImage.Warning);
}
public static MessageBoxResult ShowDialogQues(string message, string title = "提示")
{
return ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(message, title, MessageBoxButton.YesNo, MessageBoxImage.Question);
}
public static MessageBoxResult ShowDialogErr(string message, string title = "错误")
{
return ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(message, title, MessageBoxButton.OK, MessageBoxImage.Error);
}



public static void ShowNotification(string message, string title = "", MessageBoxImage messageBoxImage = MessageBoxImage.Information)
{
Notification notification = new Notification();
notification.Title = title;
notification.Message = message;
switch (messageBoxImage)
{
case MessageBoxImage.Error:
notification.ImageUrl = @"pack://application:,,,/agp.deve.utils;component/Images/PNG_Error.png";
break;
case MessageBoxImage.Warning:
notification.ImageUrl = @"pack://application:,,,/agp.deve.utils;component/Images/PNG_Warn.png";
break;
case MessageBoxImage.Question:
notification.ImageUrl = @"pack://application:,,,/agp.deve.utils;component/Images/PNG_Question.png";
break;
default:
notification.ImageUrl = @"pack://application:,,,/agp.deve.utils;component/Images/PNG_Information.png";
break;
}
FrameworkApplication.AddNotification(notification);
}

public static void ShowNotificationInfo(string message, string title = "提示")
{
Notification notification = new Notification();
notification.Title = title;
notification.Message = message;
notification.ImageUrl = @"pack://application:,,,/ArcGIS.Desktop.Resources;component/Images/GenericInformation16.png";
FrameworkApplication.AddNotification(notification);
}
public static void ShowNotificationWarn(string message, string title = "异常")
{
Notification notification = new Notification();
notification.Title = title;
notification.Message = message;
notification.ImageUrl = @"pack://application:,,,/ArcGIS.Desktop.Resources;component/Images/DialogWarningAlert16.png";
FrameworkApplication.AddNotification(notification);
}
public static void ShowNotificationQues(string message, string title = "提示")
{
Notification notification = new Notification();
notification.Title = title;
notification.Message = message;
notification.ImageUrl = @"pack://application:,,,/ArcGIS.Desktop.Resources;component/Images/GenericQuestionAdornment16.png";
FrameworkApplication.AddNotification(notification);
}
public static void ShowNotificationErr(string message, string title = "错误")
{
Notification notification = new Notification();
notification.Title = title;
notification.Message = message;
notification.ImageUrl = @"pack://application:,,,/ArcGIS.Desktop.Resources;component/Images/GenericError16.png";
FrameworkApplication.AddNotification(notification);
}
public static void ShowNotificationSucc(string message, string title = "成功")
{
Notification notification = new Notification();
notification.Title = title;
notification.Message = message;
notification.ImageUrl = @"pack://application:,,,/ArcGIS.Desktop.Resources;component/Images/StatusSuccess16.png";
FrameworkApplication.AddNotification(notification);
}
}

ProPortalUtils

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
public class ProPortalUtils
{
public static async Task<Dictionary<string,string>> GetPortalFolders()
{
Dictionary<string, string> lstFloders = new Dictionary<string, string>();
lstFloders.Add("根目录", "");
bool _isSignedOn = true;
string _userName = "";
try
{
await QueuedTask.Run(async () =>
{
var portal = ArcGISPortalManager.Current.GetActivePortal();
if (portal != null)
{
_isSignedOn = portal.IsSignedOn();
if (_isSignedOn)
{
_userName = portal.GetSignOnUsername();
PortalUserContent c = await portal.GetUserContentAsync(_userName);
IReadOnlyList<PortalFolder> folders = c.PortalFolders;
foreach (PortalFolder folder in folders)
lstFloders.Add(folder.Name, folder.Name);
}
}
return true;
});
}
catch (Exception ex)
{
//LogUtils.AppLog("Portal文件夹目录获取失败!", Enum.LogLevel.Error, ex);
}
return lstFloders;
}
}

ProProjectUtils

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
87
88
89
90
91
92
93
94
95
96
97
public class ProProjectUtils
{
public static bool CheckMapView(List<MapType> mapTypes = null, bool showMessage = true)
{
if (MapView.Active != null && MapView.Active.Map != null)
{
if (mapTypes == null)
return true;
else
{
if (mapTypes.Contains(MapView.Active.Map.MapType))
return true;
}
}
if (showMessage)
{
string str = null;
if (mapTypes != null)
{
foreach (var item in mapTypes)
{
if (str != null)
str += " 或 ";
str += GetMapTypeZH(item);
}
ProMessageUtils.ShowDialog($"请先打开并选择 {str}!", "提示");
}
else
ProMessageUtils.ShowDialog($"请先打开并选择 地图 !", "提示");
}
return false;
}
//public static async Task<bool> CheckView2()
//{
// List<MapProjectItem> mapList = Project.Current.GetItems<MapProjectItem>().ToList();
// foreach (var item in FrameworkApplication.Panes)
// {
// List<Pane> panes = FrameworkApplication.Panes.Find("esri_mapping_mapPane");
// if (panes != null && panes.Count > 0)
// {
// panes[0].Activate();
// return await Task.Run(async () =>
// {
// int wait = 0;
// while (wait < 10 && (MapView.Active == null || MapView.Active.Map == null))
// {
// await Task.Delay(1000);
// wait++;
// }
// if (wait >= 10)
// {
// ProMessageUtils.ShowDialog("加载地图视图超时,请稍后加载...", "提示");
// return false;
// }
// return true;
// });
// }
// else
// {
// ProMessageUtils.ShowDialog("请先打开并选择地图视图!", "提示");
// return false;
// }
// }
// return true;
//}
public static MapProjectItem SelectMap(MapType mapType = MapType.Map)
{
List<MapProjectItem> items = Project.Current.GetItems<MapProjectItem>().ToList();
List<MapProjectItem> mapItems = new List<MapProjectItem>();
foreach (var item in items)
if (item.MapType == mapType)
mapItems.Add(item);
if (mapItems.Count < 1)
{
ProMessageUtils.ShowDialogWarn($"未检测到{GetMapTypeZH(mapType)},请创建!");
return null;
}
Wnd_SelectMap wnd_SelectMap = new Wnd_SelectMap(mapItems);
wnd_SelectMap.Title = "选择 " + GetMapTypeZH(mapType);
bool rst = (bool)wnd_SelectMap.ShowDialog();
if(!rst) return null;
return wnd_SelectMap.SelectedMapItem;
}

public static string GetMapTypeZH(MapType mapType)
{
switch (mapType)
{
case MapType.Map:
return "地图";
case MapType.Scene:
return "场景";
default:
return mapType.ToString();
}
}
}

ProShpUtils

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
public class ProShpUtils
{
public static async Task<FeatureClass> OpenShapefileFeatureClass(string shapefilePath)
{
string folderPath = System.IO.Path.GetDirectoryName(shapefilePath);
string shapeFileName = System.IO.Path.GetFileName(shapefilePath);
FeatureClass featureClass = null;
await ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() =>
{
FileSystemDatastore fileSystemDatastore = null;
try
{
var fileConnection = new FileSystemConnectionPath(
new Uri(folderPath), FileSystemDatastoreType.Shapefile);
fileSystemDatastore = new FileSystemDatastore(fileConnection);
featureClass = fileSystemDatastore.OpenDataset<FeatureClass>(shapeFileName);
//FeatureClass taxLotsFeatureClass = shapefile.OpenDataset<FeatureClass>("TaxLots");
//FeatureClass manHolesFeatureClass = shapefile.OpenDataset<FeatureClass>("ManHoles.shp"); // Can use the .shp extension, but its not needed.
//Table taxDetailsTableWithoutExtension = shapefile.OpenDataset<Table>("TaxDetails");
//Table taxDetailsTable = shapefile.OpenDataset<Table>("TaxDetails.dbf");
}
catch(Exception ex)
{
LogUtils.AppLog("获取ShapeFile文件FeatureClass失败!", Enum.LogLevel.Warning, ex);
}
finally { if (fileSystemDatastore != null) { fileSystemDatastore.Dispose(); } }
});
return featureClass;
}

public static void Create()
{
string folderPath = "E:\\files\\work\\arcgis files\\pro\\MyProject\\data\\ShapeFile";
FileSystemDatastore fileSystemDatastore = null;
try
{
var fileConnection = new FileSystemConnectionPath(
new Uri(folderPath), FileSystemDatastoreType.Shapefile);
fileSystemDatastore = new FileSystemDatastore(fileConnection);
}
catch(Exception ex)
{

}
finally { if (fileSystemDatastore != null) { fileSystemDatastore.Dispose(); } }
}
}

ProStyleUtils

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class ProStyleUtils
{
public static async Task<StyleProjectItem >GetAppStyleProjectItem()
{
string name = Path.GetFileNameWithoutExtension(AppConfig.Path_File_AppStyle_Symbol);
IEnumerable<StyleProjectItem> enumerable = Project.Current.GetItems<StyleProjectItem>();
StyleProjectItem? styleProjectItem = enumerable.FirstOrDefault(s => s.Name == name);
if(styleProjectItem == null)
{
if (!File.Exists(AppConfig.Path_File_AppStyle_Symbol))
{
ProMessageUtils.ShowDialog("未找到系统样式文件:\r\n" + AppConfig.Path_File_AppStyle_Symbol, "提示", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Warning);
return null;
}
await QueuedTask.Run(() =>
{
Project.Current.AddStyle(AppConfig.Path_File_AppStyle_Symbol);
});
enumerable = Project.Current.GetItems<StyleProjectItem>();
styleProjectItem = enumerable.FirstOrDefault(s => s.Name == name);
}
return styleProjectItem;
}
}

ProTableUtils

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
public class ProTableUtils
{
/// <summary>
/// 更新/插入表记录,必须在QueueTask.Run中执行!
/// </summary>
/// <param name="table">目标数据表</param>
/// <param name="dataTable">源数据表</param>
/// <param name="PrimKey">主键字段</param>
/// <param name="ps">进度器</param>
/// <returns>结果</returns>
public static bool UpdateOrInsert(Table table, DataTable dataTable, string PrimKey, ProgressorSource ps = null)
{
bool containsPriKeyCol = dataTable.Columns.Contains(PrimKey);
if (!containsPriKeyCol)
{
ProMessageUtils.ShowDialog($"数据表中缺失主键字段:[{PrimKey}]!", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
return false;
}
for (int i = 0; i < dataTable.Rows.Count; i++)
{
if (ps != null)
ps.Message = $"更新数据...({i + 1}/{dataTable.Rows.Count})";
DataRow row = dataTable.Rows[i];
bool recordIsExists = false;
if (!string.IsNullOrEmpty(PrimKey))
{
object val = row[PrimKey];
QueryFilter queryFilter = new QueryFilter();
queryFilter.WhereClause = $"{PrimKey}='{val}'";
using (RowCursor rowCursor = table.Search(queryFilter))
{
while (rowCursor.MoveNext())
{
recordIsExists = true;
foreach (DataColumn col in dataTable.Columns)
{
try
{
rowCursor.Current[col.ColumnName] = row[col];
}
catch (Exception ex)
{
LogUtils.AppLog("更新实体数据异常!", Enum.LogLevel.Error, ex);
}
}
rowCursor.Current.Store();
}
}
}
if (!recordIsExists)
{
using (RowBuffer rowBuffer = table.CreateRowBuffer())
using (Row tableRow = table.CreateRow(rowBuffer))
{
foreach (DataColumn col in dataTable.Columns)
{
try
{
Field field = tableRow.GetFields().FirstOrDefault(f => f.Name.ToLower() == col.ColumnName.ToLower());
if (field != null && field.IsEditable)
tableRow[col.ColumnName] = row[col];
}
catch (Exception ex)
{
LogUtils.AppLog("插入实体数据异常!", Enum.LogLevel.Error, ex);
}
}
tableRow.Store();
}
}
}
return true;
}

/// <summary>
/// 更新/插入表记录,必须在QueueTask.Run中执行!
/// </summary>
/// <param name="table">目标数据表</param>
/// <param name="dataTable">源数据表</param>
/// <param name="PrimKey">主键字段</param>
/// <param name="ps">进度器</param>
/// <returns>结果</returns>
public static bool UpdateOrInsert(Table table, DataTable dataTable, string[] PrimKey, ProgressorSource ps = null)
{
foreach (string key in PrimKey)
{
bool containsPriKeyCol = dataTable.Columns.Contains(key);
if (!containsPriKeyCol)
{
ProMessageUtils.ShowDialog($"数据表中缺失主键字段:[{key}]!", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
return false;
}
}
for (int i = 0; i < dataTable.Rows.Count; i++)
{
if (ps != null)
ps.Message = $"更新数据...({i + 1}/{dataTable.Rows.Count})";
DataRow row = dataTable.Rows[i];
QueryFilter queryFilter = new QueryFilter();
for (int k = 0; k < PrimKey.Length; k++)
{
object val = row[PrimKey[k]];
queryFilter.WhereClause += (k == 0 ? "" : " AND ") + $"{PrimKey[k]}='{val}'";
}
bool recordIsExists = false;
using (RowCursor rowCursor = table.Search(queryFilter))
{
while (rowCursor.MoveNext())
{
recordIsExists = true;
foreach (DataColumn col in dataTable.Columns)
{
try
{
rowCursor.Current[col.ColumnName] = row[col];
}
catch (Exception ex)
{
LogUtils.AppLog("更新实体数据异常!", Enum.LogLevel.Error, ex);
}
}
rowCursor.Current.Store();
}
}
if (!recordIsExists)
{
using (RowBuffer rowBuffer = table.CreateRowBuffer())
using (Row tableRow = table.CreateRow(rowBuffer))
{
foreach (DataColumn col in dataTable.Columns)
{
try
{
object v = row[col];
tableRow[col.ColumnName] = v;
}
catch (Exception ex)
{
LogUtils.AppLog("插入实体数据异常!", Enum.LogLevel.Error, ex);
}
}
tableRow.Store();
}
}
}
return true;
}

/// <summary>
/// 更新/插入表记录,必须在QueueTask.Run中执行!
/// </summary>
/// <param name="table">目标数据表</param>
/// <param name="tableSource">源数据表</param>
/// <param name="PrimKey">主键字段</param>
/// <param name="ps">进度器</param>
/// <returns>结果</returns>
public static bool UpdateOrInsert(Table table, Table tableSource, string PrimKey, ProgressorSource ps = null)
{
IReadOnlyList<Field> fieldsSource = tableSource.GetDefinition().GetFields();
if (!string.IsNullOrEmpty(PrimKey))
{
Field field = fieldsSource.FirstOrDefault(f => f.Name.ToLower() == PrimKey.ToLower());
if (field == null)
{
ProMessageUtils.ShowDialog($"数据表中缺失主键字段:[{PrimKey}]!", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
return false;
}
}
using (RowCursor rowCursorSource = tableSource.Search())
{
long count = tableSource.GetCount();
long i = 0;
while (rowCursorSource.MoveNext())
{
if (ps != null)
ps.Progressor.Message = $"更新数据...({++i}/{count})";
bool recordIsExists = false;
if (!string.IsNullOrEmpty(PrimKey))
{
object valPrim = rowCursorSource.Current[PrimKey];
QueryFilter queryFilter = new QueryFilter();
queryFilter.WhereClause = $"{PrimKey}='{valPrim}'";
using (RowCursor rowCursor = table.Search(queryFilter))
{
while (rowCursor.MoveNext())
{
recordIsExists = true;
foreach (Field fld in fieldsSource)
{
try
{
rowCursor.Current[fld.Name] = rowCursorSource.Current[fld.Name];
}
catch (Exception ex)
{
LogUtils.AppLog("更新实体数据异常!", Enum.LogLevel.Error, ex);
}
}
rowCursor.Current.Store();
}
}
}
if (!recordIsExists)
{
using (RowBuffer rowBuffer = table.CreateRowBuffer())
using (Row tableRow = table.CreateRow(rowBuffer))
{
foreach (Field fld in fieldsSource)
{
try
{
Field? field = tableRow.GetFields().FirstOrDefault(f => f.Name == fld.Name);
if (field == null || !field.IsEditable)
continue;
tableRow[fld.Name] = rowCursorSource.Current[fld.Name];
}
catch (Exception ex)
{
LogUtils.AppLog("插入实体数据异常!", Utils.Enum.LogLevel.Error, ex);
}
}
tableRow.Store();
}
}
}
}
return true;
}

/// <summary>
/// 更新/插入表记录,必须在QueueTask.Run中执行!
/// </summary>
/// <param name="table">目标数据表</param>
/// <param name="tableSource">源数据表</param>
/// <param name="PrimKey">主键字段</param>
/// <param name="ps">进度器</param>
/// <returns>结果</returns>
public static bool UpdateOrInsert(Table table, Table tableSource, string[] PrimKey, ProgressorSource ps = null)
{
IReadOnlyList<Field> fieldsSource = tableSource.GetDefinition().GetFields();
foreach (string key in PrimKey)
{
Field field = fieldsSource.FirstOrDefault(f => f.Name.ToLower() == key.ToLower());
if (field == null)
{
ProMessageUtils.ShowDialog($"数据表中缺失主键字段:[{key}]!", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
return false;
}
}
using (RowCursor rowCursorSource = tableSource.Search())
{
long count = tableSource.GetCount();
long i = 0;
while (rowCursorSource.MoveNext())
{
if (ps != null)
ps.Message = $"更新数据...({++i}/{count})";
QueryFilter queryFilter = new QueryFilter();
for (int k = 0; k < PrimKey.Length; k++)
{
object valPrim = rowCursorSource.Current[PrimKey[k]];
queryFilter.WhereClause += (k == 0 ? "" : " AND ") + $"{PrimKey[k]}='{valPrim}'";
}
bool recordIsExists = false;
using (RowCursor rowCursor = table.Search(queryFilter))
{
while (rowCursor.MoveNext())
{
recordIsExists = true;
foreach (Field fld in fieldsSource)
{
try
{
rowCursor.Current[fld.Name] = rowCursorSource.Current[fld.Name];
}
catch (Exception ex)
{
LogUtils.AppLog("更新实体数据异常!", Enum.LogLevel.Error, ex);
}
}
rowCursor.Current.Store();
}
}
if (!recordIsExists)
{
using (RowBuffer rowBuffer = table.CreateRowBuffer())
using (Row tableRow = table.CreateRow(rowBuffer))
{
foreach (Field fld in fieldsSource)
{
try
{
tableRow[fld.Name] = rowCursorSource.Current[fld.Name];
}
catch (Exception ex)
{
LogUtils.AppLog("插入实体数据异常!", Utils.Enum.LogLevel.Error, ex);
}
}
tableRow.Store();
}
}
}
}
return true;
}
}